* Re: [PATCH 5/5] arm64: dts: Add device tree source for the Au-Zone Maivin Starter Kit
From: Francesco Dolcini @ 2024-04-03 7:06 UTC (permalink / raw)
To: Laurent Pinchart, Shawn Guo
Cc: devicetree, imx, linux-arm-kernel, Trevor Zaharichuk, Greg Lytle,
Shawn Guo, Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
In-Reply-To: <ZgyjE05p/1NZnzaK@dragon>
Hello Laurent,
On Wed, Apr 03, 2024 at 08:30:11AM +0800, Shawn Guo wrote:
> On Mon, Mar 25, 2024 at 10:32:45PM +0200, Laurent Pinchart wrote:
> > diff --git a/arch/arm64/boot/dts/freescale/imx8mp-maivin.dts b/arch/arm64/boot/dts/freescale/imx8mp-maivin.dts
> > new file mode 100644
> > index 000000000000..2d1c8e782465
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/freescale/imx8mp-maivin.dts
> > @@ -0,0 +1,236 @@
[...]
> > +/* Verdin I2C_2_DSI */
> > +&i2c2 {
> > + status = "okay";
> > +
> > + clock-frequency = <400000>;
> > + scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
> > + sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
>
> We usually end property list with 'status'.
This is now a written and explicit guideline, no longer tribal knowledge,
see https://docs.kernel.org/devicetree/bindings/dts-coding-style.html#order-of-properties-in-device-node
Francesco
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v4 4/4] remoteproc: stm32: Add support of an OP-TEE TA to load the firmware
From: Arnaud POULIQUEN @ 2024-04-03 7:04 UTC (permalink / raw)
To: Mathieu Poirier
Cc: Bjorn Andersson, Jens Wiklander, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, linux-stm32, linux-arm-kernel, linux-remoteproc,
linux-kernel, op-tee, devicetree
In-Reply-To: <ZgrW2avODv29vWNP@p14s>
On 4/1/24 17:46, Mathieu Poirier wrote:
> On Fri, Mar 29, 2024 at 11:57:43AM +0100, Arnaud POULIQUEN wrote:
>>
>>
>> On 3/27/24 18:14, Mathieu Poirier wrote:
>>> On Tue, Mar 26, 2024 at 08:31:33PM +0100, Arnaud POULIQUEN wrote:
>>>>
>>>>
>>>> On 3/25/24 17:51, Mathieu Poirier wrote:
>>>>> On Fri, Mar 08, 2024 at 03:47:08PM +0100, Arnaud Pouliquen wrote:
>>>>>> The new TEE remoteproc device is used to manage remote firmware in a
>>>>>> secure, trusted context. The 'st,stm32mp1-m4-tee' compatibility is
>>>>>> introduced to delegate the loading of the firmware to the trusted
>>>>>> execution context. In such cases, the firmware should be signed and
>>>>>> adhere to the image format defined by the TEE.
>>>>>>
>>>>>> Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
>>>>>> ---
>>>>>> Updates from V3:
>>>>>> - remove support of the attach use case. Will be addressed in a separate
>>>>>> thread,
>>>>>> - add st_rproc_tee_ops::parse_fw ops,
>>>>>> - inverse call of devm_rproc_alloc()and tee_rproc_register() to manage cross
>>>>>> reference between the rproc struct and the tee_rproc struct in tee_rproc.c.
>>>>>> ---
>>>>>> drivers/remoteproc/stm32_rproc.c | 60 +++++++++++++++++++++++++++++---
>>>>>> 1 file changed, 56 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
>>>>>> index 8cd838df4e92..13df33c78aa2 100644
>>>>>> --- a/drivers/remoteproc/stm32_rproc.c
>>>>>> +++ b/drivers/remoteproc/stm32_rproc.c
>>>>>> @@ -20,6 +20,7 @@
>>>>>> #include <linux/remoteproc.h>
>>>>>> #include <linux/reset.h>
>>>>>> #include <linux/slab.h>
>>>>>> +#include <linux/tee_remoteproc.h>
>>>>>> #include <linux/workqueue.h>
>>>>>>
>>>>>> #include "remoteproc_internal.h"
>>>>>> @@ -49,6 +50,9 @@
>>>>>> #define M4_STATE_STANDBY 4
>>>>>> #define M4_STATE_CRASH 5
>>>>>>
>>>>>> +/* Remote processor unique identifier aligned with the Trusted Execution Environment definitions */
>>>>>
>>>>> Why is this the case? At least from the kernel side it is possible to call
>>>>> tee_rproc_register() with any kind of value, why is there a need to be any
>>>>> kind of alignment with the TEE?
>>>>
>>>>
>>>> The use of the proc_id is to identify a processor in case of multi co-processors.
>>>>
>>>
>>> That is well understood.
>>>
>>>> For instance we can have a system with A DSP and a modem. We would use the same
>>>> TEE service, but
>>>
>>> That too.
>>>
>>>> the TEE driver will probably be different, same for the signature key.
>>>
>>> What TEE driver are we talking about here?
>>
>> In OP-TEE remoteproc frameork is divided in 2 or 3 layers:
>>
>> - the remoteproc Trusted Application (TA) [1] which is platform agnostic
>> - The remoteproc Pseudo Trusted Application (PTA) [2] which is platform
>> dependent and can rely on the proc ID to retrieve the context.
>> - the remoteproc driver (optional for some platforms) [3], which is in charge
>> of DT parsing and platform configuration.
>>
>
> That part makes sense.
>
>> Here TEE driver can be interpreted by remote PTA and/or platform driver.
>>
>
> I have to guess PTA means "Platform Trusted Application" but I have no
> guarantee, adding to the level of (already high) confusion brought on by this
> patchset.
As mentioned above, PTA is Pseudo Trusted Application. It is an interface
exposed by OP-TEE core to the OP-TEE application.
In this case PTA is used to implement the platform part.
If you need more details about the remoteproc framework in OP-TEE, there is a
link in the to a presentation in the cover letter.
>
>> [1]
>> https://elixir.bootlin.com/op-tee/latest/source/ta/remoteproc/src/remoteproc_core.c
>> [2]
>> https://elixir.bootlin.com/op-tee/latest/source/core/pta/stm32mp/remoteproc_pta.c
>> [3]
>> https://elixir.bootlin.com/op-tee/latest/source/core/drivers/remoteproc/stm32_remoteproc.c
>>
>>>
>>>> In such case the proc ID allows to identify the the processor you want to address.
>>>>
>>>
>>> That too is well understood, but there is no alignment needed with the TEE, i.e
>>> the TEE application is not expecting a value of '0'. We could set
>>> STM32_MP1_M4_PROC_ID to 0xDEADBEEF and things would work. This driver won't go
>>> anywhere for as long as it is not the case.
>>
>>
>> Here I suppose that you do not challenge the rproc_ID use in general, but for
>> the stm32mp1 platform as we have only one remote processor. I'm right?
>
> That is correct - I understand the need for an rproc_ID. The problem is with
> the comment that states that '0' is aligned with the TEE definitions, which in
> my head means hard coded value and a big red flag. What it should say is
> "aligned with the TEE device tree definition".
>
>>
>> In OP-TEE the check is done here:
>> https://elixir.bootlin.com/op-tee/latest/source/core/drivers/remoteproc/stm32_remoteproc.c#L64
>>
>> If driver does not register the proc ID an error is returned indicating that the
>> feature is not supported.
>>
>> In case of stm32mp1 yes we could consider it as useless as we have only one
>> remote proc.
>>
>> Nevertheless I can not guaranty that a customer will not add an external
>> companion processor that uses OP-TEE to authenticate the associated firmware. As
>> the trusted Application is the unique entry point. he will need the proc_id to
>> identify the target at PTA level.
>>
>> So from my point of view having a proc ID on stm32MP1 (and on stm32mp2 that will
>> reuse same driver) aligned between Linux and OP-TEE is useful.
>
> I agree, for as long as it is not hard coded. The way remote processors are
> discovered in the DT is perfectly acceptable, i.e the first remote processor is
> for application X, the second for application Y...
>
>>
>> That said using a TEE_REMOTEPROC_DEFAULT_ID is something that could be
>> more generic (for linux and OP-TEE). This ID could be reuse in the stm32mp
>> driver and platform drivers with an unique internal remote processor.
>>
>
> I can't find the definition of TEE_REMOTEPROC_DEFAULT_ID anywhere, something
> that doesn't help the confusion I referred to above.
The TEE_REMOTEPROC_DEFAULT_ID does not yet exist; it is a proposal.
Nevertheless I also had in mind the addition of a "proc ID" property in the DT.
I will proceed in this way
I think I now have all the information needed to prepare a new revision.
Thanks for the time passed on this series and your advises
Regards,
Arnaud
>
>> It that solution would be ok for you?
>>
>> Regards,
>> Arnaud
>>
>>
>>>
>>>>
>>>>>
>>>>>> +#define STM32_MP1_M4_PROC_ID 0
>>>>>> +
>>>>>> struct stm32_syscon {
>>>>>> struct regmap *map;
>>>>>> u32 reg;
>>>>>> @@ -257,6 +261,19 @@ static int stm32_rproc_release(struct rproc *rproc)
>>>>>> return 0;
>>>>>> }
>>>>>>
>>>>>> +static int stm32_rproc_tee_stop(struct rproc *rproc)
>>>>>> +{
>>>>>> + int err;
>>>>>> +
>>>>>> + stm32_rproc_request_shutdown(rproc);
>>>>>> +
>>>>>> + err = tee_rproc_stop(rproc);
>>>>>> + if (err)
>>>>>> + return err;
>>>>>> +
>>>>>> + return stm32_rproc_release(rproc);
>>>>>> +}
>>>>>> +
>>>>>> static int stm32_rproc_prepare(struct rproc *rproc)
>>>>>> {
>>>>>> struct device *dev = rproc->dev.parent;
>>>>>> @@ -693,8 +710,19 @@ static const struct rproc_ops st_rproc_ops = {
>>>>>> .get_boot_addr = rproc_elf_get_boot_addr,
>>>>>> };
>>>>>>
>>>>>> +static const struct rproc_ops st_rproc_tee_ops = {
>>>>>> + .prepare = stm32_rproc_prepare,
>>>>>> + .start = tee_rproc_start,
>>>>>> + .stop = stm32_rproc_tee_stop,
>>>>>> + .kick = stm32_rproc_kick,
>>>>>> + .load = tee_rproc_load_fw,
>>>>>> + .parse_fw = tee_rproc_parse_fw,
>>>>>> + .find_loaded_rsc_table = tee_rproc_find_loaded_rsc_table,
>>>>>> +};
>>>>>> +
>>>>>> static const struct of_device_id stm32_rproc_match[] = {
>>>>>> - { .compatible = "st,stm32mp1-m4" },
>>>>>> + {.compatible = "st,stm32mp1-m4",},
>>>>>> + {.compatible = "st,stm32mp1-m4-tee",},
>>>>>> {},
>>>>>> };
>>>>>> MODULE_DEVICE_TABLE(of, stm32_rproc_match);
>>>>>> @@ -853,6 +881,7 @@ static int stm32_rproc_probe(struct platform_device *pdev)
>>>>>> struct device *dev = &pdev->dev;
>>>>>> struct stm32_rproc *ddata;
>>>>>> struct device_node *np = dev->of_node;
>>>>>> + struct tee_rproc *trproc = NULL;
>>>>>> struct rproc *rproc;
>>>>>> unsigned int state;
>>>>>> int ret;
>>>>>> @@ -861,9 +890,26 @@ static int stm32_rproc_probe(struct platform_device *pdev)
>>>>>> if (ret)
>>>>>> return ret;
>>>>>>
>>>>>> - rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
>>>>>> - if (!rproc)
>>>>>> - return -ENOMEM;
>>>>>> + if (of_device_is_compatible(np, "st,stm32mp1-m4-tee")) {
>>>>>> + /*
>>>>>> + * Delegate the firmware management to the secure context.
>>>>>> + * The firmware loaded has to be signed.
>>>>>> + */
>>>>>> + rproc = devm_rproc_alloc(dev, np->name, &st_rproc_tee_ops, NULL, sizeof(*ddata));
>>>>>> + if (!rproc)
>>>>>> + return -ENOMEM;
>>>>>> +
>>>>>> + trproc = tee_rproc_register(dev, rproc, STM32_MP1_M4_PROC_ID);
>>>>>> + if (IS_ERR(trproc)) {
>>>>>> + dev_err_probe(dev, PTR_ERR(trproc),
>>>>>> + "signed firmware not supported by TEE\n");
>>>>>> + return PTR_ERR(trproc);
>>>>>> + }
>>>>>> + } else {
>>>>>> + rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, NULL, sizeof(*ddata));
>>>>>> + if (!rproc)
>>>>>> + return -ENOMEM;
>>>>>> + }
>>>>>>
>>>>>> ddata = rproc->priv;
>>>>>>
>>>>>> @@ -915,6 +961,9 @@ static int stm32_rproc_probe(struct platform_device *pdev)
>>>>>> dev_pm_clear_wake_irq(dev);
>>>>>> device_init_wakeup(dev, false);
>>>>>> }
>>>>>> + if (trproc)
>>>>>
>>>>> if (rproc->tee_interface)
>>>>>
>>>>>
>>>>> I am done reviewing this set.
>>>>
>>>> Thank for your review!
>>>> Arnaud
>>>>
>>>>>
>>>>> Thanks,
>>>>> Mathieu
>>>>>
>>>>>> + tee_rproc_unregister(trproc);
>>>>>> +
>>>>>> return ret;
>>>>>> }
>>>>>>
>>>>>> @@ -935,6 +984,9 @@ static void stm32_rproc_remove(struct platform_device *pdev)
>>>>>> dev_pm_clear_wake_irq(dev);
>>>>>> device_init_wakeup(dev, false);
>>>>>> }
>>>>>> + if (rproc->tee_interface)
>>>>>> + tee_rproc_unregister(rproc->tee_interface);
>>>>>> +
>>>>>> }
>>>>>>
>>>>>> static int stm32_rproc_suspend(struct device *dev)
>>>>>> --
>>>>>> 2.25.1
>>>>>>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 1/9] dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id
From: Shawn Sung @ 2024-04-03 6:55 UTC (permalink / raw)
To: CK Hu, Jassi Brar, AngeloGioacchino Del Regno
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
Hsiao Chien Sung, Jason-JH . Lin, Houlong Wei, linux-kernel,
devicetree, linux-arm-kernel, linux-mediatek
In-Reply-To: <20240403065603.21920-1-shawn.sung@mediatek.com>
From: "Jason-JH.Lin" <jason-jh.lin@mediatek.com>
There are 2 kind of GCE event signal:
- The SW token means: a GCE event signal triggered by SW drivers.
e.g. SW driver append a GCE command to set a GCE event after a specific
GCE command. Or SW driver use CPU to write a event id to GCE register to
trigger the GCE event corresponding to that event id.
- The HW event means: a GCE event signal triggered by HW engines.
e.g. When HW OVL fetches all the data in frame buffer, HW OVL will send
a frame done irq and also send a frame done GCE event via HW bus directly.
CMDQ_SYNC_TOKEN_SECURE_THR_EOF is a SW token event that is set in the
end of each cmdq secure pkt. It is used as a secure irq to notify
CMDQ driver in the normal world that GCE secure thread has completed
a secure cmd buffer in thee secure world.
Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
include/dt-bindings/gce/mt8195-gce.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/dt-bindings/gce/mt8195-gce.h b/include/dt-bindings/gce/mt8195-gce.h
index dcfb302b8a5bc..b6b3db82c381e 100644
--- a/include/dt-bindings/gce/mt8195-gce.h
+++ b/include/dt-bindings/gce/mt8195-gce.h
@@ -800,6 +800,12 @@
#define CMDQ_EVENT_WPE_VPP1_WPE_GCE_FRAME_DONE 969
#define CMDQ_EVENT_WPE_VPP1_WPE_DONE_SYNC_OUT 970
+/*
+ * Notify normal CMDQ there are some secure task done,
+ * this token sync with secure world.
+ */
+#define CMDQ_SYNC_TOKEN_SECURE_THR_EOF 980
+
#define CMDQ_EVENT_DP_TX_VBLANK_FALLING 994
#define CMDQ_EVENT_DP_TX_VSC_FINISH 995
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 8/9] mailbox: mediatek: Add CMDQ secure mailbox driver
From: Shawn Sung @ 2024-04-03 6:56 UTC (permalink / raw)
To: CK Hu, Jassi Brar, AngeloGioacchino Del Regno
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
Hsiao Chien Sung, Jason-JH . Lin, Houlong Wei, linux-kernel,
devicetree, linux-arm-kernel, linux-mediatek
In-Reply-To: <20240403065603.21920-1-shawn.sung@mediatek.com>
From: "Jason-JH.Lin" <jason-jh.lin@mediatek.com>
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@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
drivers/mailbox/Makefile | 2 +-
drivers/mailbox/mtk-cmdq-sec-mailbox.c | 1091 +++++++++++++++++
drivers/mailbox/mtk-cmdq-sec-tee.c | 165 +++
include/linux/mailbox/mtk-cmdq-mailbox.h | 2 +
.../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 385 ++++++
include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 158 +++
include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++
7 files changed, 1907 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 18793e6caa2f1..bd4b4d64cc317 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 0000000000000..c08d42bcc06f6
--- /dev/null
+++ b/drivers/mailbox/mtk-cmdq-sec-mailbox.c
@@ -0,0 +1,1091 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#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_EXEC_CNT_PA (0x28)
+
+#define CMDQ_TIMEOUT_DEFAULT (1000)
+#define CMDQ_NO_TIMEOUT (0xffffffff)
+#define ADDR_METADATA_MAX_COUNT_ORIGIN (8)
+
+struct cmdq_sec_task {
+ struct cmdq_task task;
+
+ /* secure CMDQ */
+ bool reset_exec;
+ u32 wait_cookie;
+ u64 engine_flag;
+ s32 scenario;
+ u64 trigger;
+ u64 exec_time;
+ struct work_struct exec_work;
+};
+
+struct cmdq_sec_thread {
+ struct cmdq_thread thread;
+
+ /* secure CMDQ */
+ u32 idx;
+ struct timer_list timeout;
+ u32 timeout_ms;
+ struct work_struct timeout_work;
+ u32 wait_cookie;
+ u32 next_cookie;
+ u32 task_cnt;
+ struct workqueue_struct *task_exec_wq;
+};
+
+/**
+ * struct cmdq_sec_context - CMDQ secure context structure.
+ * @tgid: tgid of process context.
+ * @state: state of inter-world communicatiom.
+ * @iwc_msg: buffer for inter-world communicatiom message.
+ * @tee_ctx: context structure for tee vendor.
+ *
+ * Note it is not global data, each process has its own cmdq_sec_context.
+ */
+struct cmdq_sec_context {
+ u32 tgid;
+ enum cmdq_iwc_state_enum state;
+ void *iwc_msg;
+ struct cmdq_sec_tee_context tee_ctx;
+};
+
+/**
+ * struct cmdq_sec_shared_mem - shared memory between normal and secure world
+ * @va: virtual address of share memory.
+ * @pa: physical address of share memory.
+ * @size: size of share memory.
+ *
+ */
+struct cmdq_sec_shared_mem {
+ void *va;
+ dma_addr_t pa;
+ u32 size;
+};
+
+struct cmdq_sec {
+ struct mbox_controller mbox;
+ const struct gce_sec_plat *pdata;
+ void __iomem *base;
+ phys_addr_t base_pa;
+ struct cmdq_sec_thread *sec_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 iwc_cmdq_cancel_task_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;
+ /* 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 *sec_task,
+ const u32 iwc_cmd, const u32 thrd_idx, void *data);
+
+int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt)
+{
+ struct cmdq_client *cl = (struct cmdq_client *)pkt->cl;
+ struct cmdq_thread *thread = ((struct mbox_chan *)(cl->chan))->con_priv;
+ struct cmdq_sec_thread *sec_thread = container_of(thread, struct cmdq_sec_thread, thread);
+ struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct cmdq_sec, mbox);
+ struct cmdq_operand left, right;
+ dma_addr_t addr;
+
+ if (!cmdq->shared_mem)
+ return -EFAULT;
+
+ dev_dbg(cmdq->mbox.dev, "%s %d: pkt:%p thread:%u gce:%#lx",
+ __func__, __LINE__, pkt, sec_thread->idx, (unsigned long)cmdq->base_pa);
+
+ addr = (u32)(cmdq->base_pa + CMDQ_THR_BASE +
+ CMDQ_THR_SIZE * sec_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_THR_SPR_IDX1, &left, CMDQ_LOGIC_ADD, &right);
+
+ addr = cmdq->shared_mem->pa + CMDQ_SEC_SHARED_THR_CNT_OFFSET +
+ sec_thread->idx * sizeof(u32);
+
+ 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->pdata->cmdq_event);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(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->addr_metadatas, *curr;
+
+ if (count <= sec_data->addr_metadata_max_cnt)
+ return 0;
+
+ curr = kcalloc(count, sizeof(*sec_data), GFP_KERNEL);
+ if (!curr)
+ return -ENOMEM;
+
+ if (count && sec_data->addr_metadatas)
+ memcpy(curr, prev, sizeof(*sec_data) * sec_data->addr_metadata_max_cnt);
+
+ kfree(prev);
+
+ sec_data->addr_metadatas = (uintptr_t)curr;
+ sec_data->addr_metadata_max_cnt = count;
+ return 0;
+}
+
+void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt)
+{
+ kfree(pkt->sec_data);
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_pkt_free_sec_data);
+
+int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt)
+{
+ 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;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_pkt_alloc_sec_data);
+
+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 iwc_cmdq_addr_metadata_t *meta;
+ 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_pkt_alloc_sec_data(pkt);
+ if (ret < 0)
+ return ret;
+
+ sec_data = (struct cmdq_sec_data *)pkt->sec_data;
+ idx = sec_data->addr_metadata_cnt;
+ 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->addr_metadata_max_cnt)
+ max = ADDR_METADATA_MAX_COUNT_ORIGIN;
+ else if (idx >= sec_data->addr_metadata_max_cnt)
+ max = sec_data->addr_metadata_max_cnt * 2;
+ else
+ max = sec_data->addr_metadata_max_cnt;
+
+ ret = cmdq_sec_realloc_addr_list(pkt, max);
+ if (ret)
+ return ret;
+
+ if (!sec_data->addr_metadatas) {
+ pr_info("addrMetadatas is missing");
+
+ meta = kzalloc(sizeof(*meta), GFP_KERNEL);
+ if (!meta)
+ return -ENOMEM;
+
+ sec_data->addr_metadatas = (uintptr_t)(void *)meta;
+ }
+ meta = (struct iwc_cmdq_addr_metadata_t *)(uintptr_t)sec_data->addr_metadatas;
+
+ meta[idx].instr_idx = pkt->cmd_buf_size / CMDQ_INST_SIZE - 1;
+ meta[idx].type = type;
+ meta[idx].base_handle = base;
+ meta[idx].offset = offset;
+ meta[idx].size = size;
+ meta[idx].port = port;
+ sec_data->addr_metadata_cnt += 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_pkt_alloc_sec_data(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->engs_need_dapc |= dapc_engine;
+ sec_data->engs_need_sec_port |= port_sec_engine;
+ sec_data->scenario = scenario;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(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_GPL(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 *sec_task, int sta)
+{
+ struct cmdq_cb_data data;
+
+ data.sta = sta;
+ data.pkt = sec_task->task.pkt;
+
+ pr_debug("%s sec_task:%p pkt:%p err:%d",
+ __func__, sec_task, sec_task->task.pkt, sta);
+
+ mbox_chan_received_data(sec_task->task.thread->chan, &data);
+
+ list_del_init(&sec_task->task.list_entry);
+ kfree(sec_task);
+}
+
+static bool cmdq_sec_irq_handler(struct cmdq_sec_thread *sec_thread,
+ const u32 cookie, const int err)
+{
+ struct cmdq_sec_task *sec_task;
+ struct cmdq_task *task, *temp, *cur_task = NULL;
+ struct cmdq_sec *cmdq = container_of(sec_thread->thread.chan->mbox, struct cmdq_sec, mbox);
+ unsigned long flags;
+ int done;
+
+ spin_lock_irqsave(&sec_thread->thread.chan->lock, flags);
+ if (sec_thread->wait_cookie <= cookie)
+ done = cookie - sec_thread->wait_cookie + 1;
+ else if (sec_thread->wait_cookie == (cookie + 1) % CMDQ_MAX_COOKIE_VALUE)
+ done = 0;
+ else
+ done = CMDQ_MAX_COOKIE_VALUE - sec_thread->wait_cookie + 1 + cookie + 1;
+
+ list_for_each_entry_safe(task, temp, &sec_thread->thread.task_busy_list, list_entry) {
+ if (!done)
+ break;
+
+ sec_task = container_of(task, struct cmdq_sec_task, task);
+ cmdq_sec_task_done(sec_task, err);
+
+ if (sec_thread->task_cnt)
+ sec_thread->task_cnt -= 1;
+
+ done--;
+ }
+
+ cur_task = list_first_entry_or_null(&sec_thread->thread.task_busy_list,
+ struct cmdq_task, list_entry);
+ if (err && cur_task) {
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+
+ sec_task = container_of(cur_task, struct cmdq_sec_task, task);
+
+ /* for error task, cancel, callback and done */
+ memset(&cmdq->cancel, 0, sizeof(cmdq->cancel));
+ cmdq_sec_task_submit(cmdq, sec_task, CMD_CMDQ_IWC_CANCEL_TASK,
+ sec_thread->idx, &cmdq->cancel);
+
+ cmdq_sec_task_done(sec_task, err);
+
+ spin_lock_irqsave(&sec_thread->thread.chan->lock, flags);
+
+ task = list_first_entry_or_null(&sec_thread->thread.task_busy_list,
+ struct cmdq_task, list_entry);
+ if (cur_task == task)
+ cmdq_sec_task_done(sec_task, err);
+ else
+ dev_err(cmdq->mbox.dev, "task list changed");
+
+ /*
+ * error case stop all task for secure,
+ * since secure tdrv always remove all when cancel
+ */
+ while (!list_empty(&sec_thread->thread.task_busy_list)) {
+ cur_task = list_first_entry(&sec_thread->thread.task_busy_list,
+ struct cmdq_task, list_entry);
+
+ sec_task = container_of(cur_task, struct cmdq_sec_task, task);
+ cmdq_sec_task_done(sec_task, -ECONNABORTED);
+ }
+ } else if (err) {
+ dev_dbg(cmdq->mbox.dev, "error but all task done, check notify callback");
+ }
+
+ if (list_empty(&sec_thread->thread.task_busy_list)) {
+ sec_thread->wait_cookie = 0;
+ sec_thread->next_cookie = 0;
+ sec_thread->task_cnt = 0;
+ __raw_writel(0, (void __iomem *)cmdq->shared_mem->va +
+ CMDQ_SEC_SHARED_THR_CNT_OFFSET +
+ sec_thread->idx * sizeof(u32));
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+ del_timer(&sec_thread->timeout);
+ return true;
+ }
+
+ sec_thread->wait_cookie = cookie % CMDQ_MAX_COOKIE_VALUE + 1;
+
+ mod_timer(&sec_thread->timeout, jiffies + msecs_to_jiffies(sec_thread->timeout_ms));
+ spin_unlock_irqrestore(&sec_thread->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;
+ u32 thread_max = cmdq->pdata->secure_thread_min + cmdq->pdata->secure_thread_nr;
+
+ mutex_lock(&cmdq->exec_lock);
+
+ for (i = cmdq->pdata->secure_thread_min; i <= thread_max; i++) {
+ struct cmdq_sec_thread *sec_thread = &cmdq->sec_thread[i];
+ u32 cookie = cmdq_sec_get_cookie(cmdq, sec_thread->idx);
+
+ if (cookie < sec_thread->wait_cookie || !sec_thread->task_cnt)
+ continue;
+
+ cmdq_sec_irq_handler(sec_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(&cmdq->irq_notify_work)) {
+ dev_dbg(cmdq->mbox.dev, "%s last notify callback working", __func__);
+ return;
+ }
+
+ queue_work(cmdq->notify_wq, &cmdq->irq_notify_work);
+}
+
+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)) {
+ dev_err(cmdq->mbox.dev, "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, PAGE_SIZE);
+ if (!cmdq->clt_pkt || IS_ERR(cmdq->clt_pkt)) {
+ dev_err(cmdq->mbox.dev, "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->pdata->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) {
+ dev_err(cmdq->mbox.dev, "%s failed:%d", __func__, err);
+
+ cmdq_sec_pkt_free_sec_data(cmdq->clt_pkt);
+ cmdq_pkt_destroy(cmdq->clt_pkt);
+ cmdq_mbox_destroy(cmdq->clt);
+
+ return err;
+ }
+
+ cmdq->notify_run = true;
+ dev_dbg(cmdq->mbox.dev, "%s success!", __func__);
+
+ return 0;
+}
+
+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 0;
+ }
+
+ switch (context->state) {
+ case IWC_INIT:
+ err = cmdq_sec_init_context(&context->tee_ctx);
+ if (err)
+ return err;
+ context->state = IWC_CONTEXT_INITED;
+ fallthrough;
+ case IWC_CONTEXT_INITED:
+ if (context->iwc_msg) {
+ pr_err("iwcMessage not NULL:%p", context->iwc_msg);
+ return -EINVAL;
+ }
+
+ err = cmdq_sec_allocate_wsm(&context->tee_ctx, &context->iwc_msg,
+ sizeof(struct iwc_cmdq_message_t));
+ if (err)
+ return err;
+
+ context->state = IWC_WSM_ALLOCATED;
+ fallthrough;
+ case IWC_WSM_ALLOCATED:
+ err = cmdq_sec_open_session(&context->tee_ctx, context->iwc_msg);
+ if (err)
+ return err;
+
+ context->state = IWC_SES_OPENED;
+ fallthrough;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int cmdq_sec_fill_iwc_msg(struct cmdq_sec_context *context,
+ struct cmdq_sec_task *sec_task, u32 thrd_idx)
+{
+ struct iwc_cmdq_message_t *iwc_msg = NULL;
+ struct cmdq_sec_data *data = (struct cmdq_sec_data *)sec_task->task.pkt->sec_data;
+ u32 size = 0, offset = 0, *instr;
+
+ iwc_msg = (struct iwc_cmdq_message_t *)context->iwc_msg;
+
+ if (sec_task->task.pkt->cmd_buf_size + 4 * CMDQ_INST_SIZE > CMDQ_TZ_CMD_BLOCK_SIZE) {
+ pr_err("sec_task:%p size:%zu > %u",
+ sec_task, sec_task->task.pkt->cmd_buf_size, CMDQ_TZ_CMD_BLOCK_SIZE);
+ return -EFAULT;
+ }
+
+ if (thrd_idx == CMDQ_INVALID_THREAD) {
+ iwc_msg->command.cmd_size = 0;
+ iwc_msg->command.metadata.addr_list_length = 0;
+ return -EINVAL;
+ }
+
+ iwc_msg->command.thread = thrd_idx;
+ iwc_msg->command.scenario = sec_task->scenario;
+ iwc_msg->command.eng_flag = sec_task->engine_flag;
+ size = sec_task->task.pkt->cmd_buf_size;
+ memcpy(iwc_msg->command.va_base + offset, sec_task->task.pkt->va_base, size);
+ iwc_msg->command.cmd_size += size;
+ offset += size / 4;
+
+ instr = &iwc_msg->command.va_base[iwc_msg->command.cmd_size / 4 - 4];
+ if ((u64)*instr == CMDQ_EOC_CMD)
+ instr[0] = 0;
+ else
+ pr_err("%s %d: find EOC failed: %#x %#x",
+ __func__, __LINE__, instr[1], instr[0]);
+
+ iwc_msg->command.wait_cookie = sec_task->wait_cookie;
+ iwc_msg->command.reset_exec = sec_task->reset_exec;
+
+ if (data->addr_metadata_cnt) {
+ iwc_msg->command.metadata.addr_list_length = data->addr_metadata_cnt;
+ memcpy(iwc_msg->command.metadata.addr_list,
+ (u32 *)(unsigned long)data->addr_metadatas,
+ data->addr_metadata_cnt * sizeof(struct iwc_cmdq_addr_metadata_t));
+ }
+
+ iwc_msg->command.metadata.engs_need_dapc = data->engs_need_dapc;
+ iwc_msg->command.metadata.engs_need_sec_port = data->engs_need_sec_port;
+ iwc_msg->command.normal_task_handle = (unsigned long)sec_task->task.pkt;
+
+ return 0;
+}
+
+static int cmdq_sec_session_send(struct cmdq_sec_context *context,
+ struct cmdq_sec_task *sec_task, const u32 iwc_cmd,
+ const u32 thrd_idx, struct cmdq_sec *cmdq)
+{
+ int err = 0;
+ u64 cost;
+ struct iwc_cmdq_message_t *iwc_msg = NULL;
+
+ iwc_msg = (struct iwc_cmdq_message_t *)context->iwc_msg;
+
+ memset(iwc_msg, 0, sizeof(*iwc_msg));
+ iwc_msg->cmd = iwc_cmd;
+ iwc_msg->cmdq_id = cmdq->pdata->hwid;
+ iwc_msg->command.thread = thrd_idx;
+
+ switch (iwc_cmd) {
+ case CMD_CMDQ_IWC_SUBMIT_TASK:
+ err = cmdq_sec_fill_iwc_msg(context, sec_task, thrd_idx);
+ if (err)
+ return err;
+ break;
+ case CMD_CMDQ_IWC_CANCEL_TASK:
+ iwc_msg->cancel_task.wait_cookie = sec_task->wait_cookie;
+ iwc_msg->cancel_task.thread = thrd_idx;
+ break;
+ case CMD_CMDQ_IWC_PATH_RES_ALLOCATE:
+ if (!cmdq->shared_mem || !cmdq->shared_mem->va) {
+ dev_err(cmdq->mbox.dev, "%s %d: shared_mem is NULL", __func__, __LINE__);
+ return -EFAULT;
+ }
+ iwc_msg->path_resource.size = cmdq->shared_mem->size;
+ iwc_msg->path_resource.share_memoy_pa = cmdq->shared_mem->pa;
+ iwc_msg->path_resource.use_normal_irq = 1;
+ break;
+ default:
+ break;
+ }
+
+ cmdq->sec_invoke = sched_clock();
+ dev_dbg(cmdq->mbox.dev, "%s execute cmdq:%p sec_task:%p command:%u thread:%u cookie:%d",
+ __func__, cmdq, sec_task, iwc_cmd, thrd_idx,
+ sec_task ? sec_task->wait_cookie : -1);
+
+ /* send message */
+ err = cmdq_sec_execute_session(&context->tee_ctx, 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)
+ dev_err(cmdq->mbox.dev, "%s execute timeout cmdq:%p sec_task:%p cost:%lluus",
+ __func__, cmdq, sec_task, cost);
+ else
+ dev_dbg(cmdq->mbox.dev, "%s execute done cmdq:%p sec_task:%p cost:%lluus",
+ __func__, cmdq, sec_task, cost);
+
+ if (err)
+ return err;
+
+ context->state = IWC_SES_ON_TRANSACTED;
+ return 0;
+}
+
+static int cmdq_sec_session_reply(const u32 iwc_cmd, struct iwc_cmdq_message_t *iwc_msg,
+ void *data, struct cmdq_sec_task *sec_task)
+{
+ struct iwc_cmdq_cancel_task_t *cancel = data;
+ struct cmdq_sec_data *sec_data = sec_task->task.pkt->sec_data;
+
+ if (iwc_cmd == CMD_CMDQ_IWC_SUBMIT_TASK && iwc_msg->rsp < 0) {
+ /* submit fail case copy status */
+ memcpy(&sec_data->sec_status, &iwc_msg->sec_status,
+ 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->cancel_task, sizeof(*cancel));
+ }
+
+ return iwc_msg->rsp;
+}
+
+static int cmdq_sec_task_submit(struct cmdq_sec *cmdq, struct cmdq_sec_task *sec_task,
+ const u32 iwc_cmd, const u32 thrd_idx, void *data)
+{
+ struct cmdq_sec_context *context;
+ int err = 0;
+
+ if (!cmdq->context) {
+ context = kzalloc(sizeof(*cmdq->context), GFP_ATOMIC);
+ if (!context)
+ return -ENOMEM;
+
+ cmdq->context = context;
+ cmdq->context->state = IWC_INIT;
+ cmdq->context->tgid = current->tgid;
+ }
+
+ if (cmdq->context->state == IWC_INIT)
+ cmdq_sec_setup_tee_context(&cmdq->context->tee_ctx);
+
+ err = cmdq_sec_session_init(cmdq->context);
+ if (err) {
+ dev_err(cmdq->mbox.dev, "%s %d: cmdq_sec_session_init fail: %d",
+ __func__, __LINE__, err);
+ return err;
+ }
+
+ err = cmdq_sec_irq_notify_start(cmdq);
+ if (err) {
+ dev_err(cmdq->mbox.dev, "%s %d: cmdq_sec_irq_notify_start fail: %d",
+ __func__, __LINE__, err);
+ return err;
+ }
+
+ err = cmdq_sec_session_send(cmdq->context, sec_task, iwc_cmd, thrd_idx, cmdq);
+ if (err) {
+ dev_err(cmdq->mbox.dev, "%s %d: iwc_cmd:%d err:%d sec_task:%p thread:%u gce:%#lx",
+ __func__, __LINE__, iwc_cmd, err,
+ sec_task, thrd_idx, (unsigned long)cmdq->base_pa);
+ return err;
+ }
+
+ err = cmdq_sec_session_reply(iwc_cmd, cmdq->context->iwc_msg, data, sec_task);
+ if (err) {
+ dev_err(cmdq->mbox.dev, "%s %d: cmdq_sec_session_reply fail: %d",
+ __func__, __LINE__, err);
+ return err;
+ }
+
+ return 0;
+}
+
+static int cmdq_sec_suspend(struct device *dev)
+{
+ struct cmdq_sec *cmdq = dev_get_drvdata(dev);
+
+ clk_bulk_disable_unprepare(cmdq->pdata->gce_num, cmdq->pdata->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->pdata->gce_num, cmdq->pdata->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 *sec_task = container_of(work_item,
+ struct cmdq_sec_task, exec_work);
+ struct cmdq_sec_thread *sec_thread = container_of(sec_task->task.thread,
+ struct cmdq_sec_thread, thread);
+ struct cmdq_sec *cmdq = container_of(sec_thread->thread.chan->mbox,
+ struct cmdq_sec, mbox);
+ struct cmdq_sec_data *data;
+ unsigned long flags;
+ int err;
+
+ dev_dbg(cmdq->mbox.dev, "%s gce:%#lx sec_task:%p pkt:%p thread:%u",
+ __func__, (unsigned long)cmdq->base_pa,
+ sec_task, sec_task->task.pkt, sec_thread->idx);
+
+ if (!sec_task->task.pkt->sec_data) {
+ dev_err(cmdq->mbox.dev, "pkt:%p without sec_data", sec_task->task.pkt);
+ return;
+ }
+ data = (struct cmdq_sec_data *)sec_task->task.pkt->sec_data;
+
+ mutex_lock(&cmdq->exec_lock);
+
+ spin_lock_irqsave(&sec_thread->thread.chan->lock, flags);
+ if (!sec_thread->task_cnt) {
+ mod_timer(&sec_thread->timeout, jiffies +
+ msecs_to_jiffies(sec_thread->timeout_ms));
+ sec_thread->wait_cookie = 1;
+ sec_thread->next_cookie = 1;
+ sec_thread->task_cnt = 0;
+ __raw_writel(0, (void __iomem *)cmdq->shared_mem->va +
+ CMDQ_SEC_SHARED_THR_CNT_OFFSET + sec_thread->idx * sizeof(u32));
+ }
+
+ sec_task->reset_exec = sec_thread->task_cnt ? false : true;
+ sec_task->wait_cookie = sec_thread->next_cookie;
+ sec_thread->next_cookie = (sec_thread->next_cookie + 1) % CMDQ_MAX_COOKIE_VALUE;
+ list_add_tail(&sec_task->task.list_entry, &sec_thread->thread.task_busy_list);
+ sec_thread->task_cnt += 1;
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+ sec_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_end;
+ }
+ }
+
+ if (sec_thread->task_cnt > CMDQ_MAX_TASK_IN_SECURE_THREAD) {
+ dev_err(cmdq->mbox.dev, "task_cnt:%u cannot more than %u sec_task:%p thread:%u",
+ sec_thread->task_cnt, CMDQ_MAX_TASK_IN_SECURE_THREAD,
+ sec_task, sec_thread->idx);
+ err = -EMSGSIZE;
+ goto task_end;
+ }
+
+ err = cmdq_sec_task_submit(cmdq, sec_task, CMD_CMDQ_IWC_SUBMIT_TASK,
+ sec_thread->idx, NULL);
+ if (err)
+ dev_err(cmdq->mbox.dev, "cmdq_sec_task_submit err:%d sec_task:%p thread:%u",
+ err, sec_task, sec_thread->idx);
+
+task_end:
+ if (err) {
+ struct cmdq_cb_data cb_data;
+
+ cb_data.sta = err;
+ cb_data.pkt = sec_task->task.pkt;
+ mbox_chan_received_data(sec_thread->thread.chan, &cb_data);
+
+ spin_lock_irqsave(&sec_thread->thread.chan->lock, flags);
+ if (!sec_thread->task_cnt)
+ dev_err(cmdq->mbox.dev, "thread:%u task_cnt:%u cannot below zero",
+ sec_thread->idx, sec_thread->task_cnt);
+ else
+ sec_thread->task_cnt -= 1;
+
+ sec_thread->next_cookie = (sec_thread->next_cookie - 1 +
+ CMDQ_MAX_COOKIE_VALUE) % CMDQ_MAX_COOKIE_VALUE;
+ list_del(&sec_task->task.list_entry);
+ dev_dbg(cmdq->mbox.dev, "gce:%#lx err:%d sec_task:%p pkt:%p",
+ (unsigned long)cmdq->base_pa, err, sec_task, sec_task->task.pkt);
+ dev_dbg(cmdq->mbox.dev, "thread:%u task_cnt:%u wait_cookie:%u next_cookie:%u",
+ sec_thread->idx, sec_thread->task_cnt,
+ sec_thread->wait_cookie, sec_thread->next_cookie);
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+
+ kfree(sec_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_thread *thread = (struct cmdq_thread *)chan->con_priv;
+ struct cmdq_sec_thread *sec_thread = container_of(thread, struct cmdq_sec_thread, thread);
+ struct cmdq_sec_task *sec_task;
+
+ if (!sec_data)
+ return -EINVAL;
+
+ sec_task = kzalloc(sizeof(*sec_task), GFP_ATOMIC);
+ if (!sec_task)
+ return -ENOMEM;
+
+ sec_task->task.pkt = pkt;
+ sec_task->task.thread = thread;
+ sec_task->scenario = sec_data->scenario;
+ sec_task->engine_flag = sec_data->engs_need_dapc | sec_data->engs_need_sec_port;
+
+ INIT_WORK(&sec_task->exec_work, cmdq_sec_task_exec_work);
+ queue_work(sec_thread->task_exec_wq, &sec_task->exec_work);
+ return 0;
+}
+
+static void cmdq_sec_thread_timeout(struct timer_list *t)
+{
+ struct cmdq_sec_thread *sec_thread = from_timer(sec_thread, t, timeout);
+ struct cmdq_sec *cmdq = container_of(sec_thread->thread.chan->mbox, struct cmdq_sec, mbox);
+
+ if (!work_pending(&sec_thread->timeout_work))
+ queue_work(cmdq->timeout_wq, &sec_thread->timeout_work);
+}
+
+static void cmdq_sec_task_timeout_work(struct work_struct *work_item)
+{
+ struct cmdq_sec_thread *sec_thread = container_of(work_item,
+ struct cmdq_sec_thread, timeout_work);
+ struct cmdq_sec *cmdq = container_of(sec_thread->thread.chan->mbox,
+ struct cmdq_sec, mbox);
+ struct cmdq_task *task;
+ struct cmdq_sec_task *sec_task;
+ unsigned long flags;
+ u64 duration;
+ u32 cookie;
+
+ mutex_lock(&cmdq->exec_lock);
+
+ spin_lock_irqsave(&sec_thread->thread.chan->lock, flags);
+ if (list_empty(&sec_thread->thread.task_busy_list)) {
+ dev_err(cmdq->mbox.dev, "thread:%u task_list is empty", sec_thread->idx);
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+ goto done;
+ }
+
+ task = list_first_entry(&sec_thread->thread.task_busy_list,
+ struct cmdq_task, list_entry);
+ sec_task = container_of(task, struct cmdq_sec_task, task);
+ duration = div_u64(sched_clock() - sec_task->trigger, 1000000);
+ if (duration < sec_thread->timeout_ms) {
+ mod_timer(&sec_thread->timeout, jiffies +
+ msecs_to_jiffies(sec_thread->timeout_ms - duration));
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+ goto done;
+ }
+
+ cookie = cmdq_sec_get_cookie(cmdq, sec_thread->idx);
+ spin_unlock_irqrestore(&sec_thread->thread.chan->lock, flags);
+
+ dev_err(cmdq->mbox.dev, "%s duration:%llu cookie:%u thread:%u",
+ __func__, duration, cookie, sec_thread->idx);
+ cmdq_sec_irq_handler(sec_thread, cookie, -ETIMEDOUT);
+
+done:
+ mutex_unlock(&cmdq->exec_lock);
+}
+
+static int cmdq_sec_mbox_startup(struct mbox_chan *chan)
+{
+ struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
+ struct cmdq_sec_thread *sec_thread = container_of(thread,
+ struct cmdq_sec_thread, thread);
+ char name[20];
+
+ timer_setup(&sec_thread->timeout, cmdq_sec_thread_timeout, 0);
+
+ INIT_WORK(&sec_thread->timeout_work, cmdq_sec_task_timeout_work);
+ snprintf(name, sizeof(name), "task_exec_wq_%u", sec_thread->idx);
+ sec_thread->task_exec_wq = create_singlethread_workqueue(name);
+ return 0;
+}
+
+static void cmdq_sec_mbox_shutdown(struct mbox_chan *chan)
+{
+}
+
+static int cmdq_sec_mbox_flush(struct mbox_chan *chan, unsigned long timeout)
+{
+ struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
+ struct cmdq_sec *cmdq = container_of(thread->chan->mbox, struct cmdq_sec, mbox);
+ int i;
+ u32 thread_max = cmdq->pdata->secure_thread_min + cmdq->pdata->secure_thread_nr;
+
+ mutex_lock(&cmdq->exec_lock);
+
+ if (list_empty(&thread->task_busy_list)) {
+ mutex_unlock(&cmdq->exec_lock);
+ return 0;
+ }
+
+ for (i = cmdq->pdata->secure_thread_min; i < thread_max; i++) {
+ struct cmdq_sec_thread *sec_thread = &cmdq->sec_thread[i];
+ u32 cookie = cmdq_sec_get_cookie(cmdq, sec_thread->idx);
+
+ if (cookie < sec_thread->wait_cookie || !sec_thread->task_cnt)
+ continue;
+
+ cmdq_sec_irq_handler(sec_thread, cookie, -ECONNABORTED);
+ }
+
+ mutex_unlock(&cmdq->exec_lock);
+ return 0;
+}
+
+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,
+};
+
+static struct mbox_chan *cmdq_sec_mbox_of_xlate(struct mbox_controller *mbox,
+ const struct of_phandle_args *sp)
+{
+ struct cmdq_thread *thread;
+ struct cmdq_sec_thread *sec_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_thread *)mbox->chans[idx].con_priv;
+ thread->chan = &mbox->chans[idx];
+ thread->priority = sp->args[1];
+ sec_thread = container_of(thread, struct cmdq_sec_thread, thread);
+ sec_thread->timeout_ms = CMDQ_NO_TIMEOUT;
+
+ return &mbox->chans[idx];
+}
+
+static int cmdq_sec_probe(struct platform_device *pdev)
+{
+ int i, err;
+ struct cmdq_sec *cmdq;
+ struct device *dev = &pdev->dev;
+ struct device *gce_dev;
+ struct resource *res;
+
+ cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
+ if (!cmdq)
+ return -ENOMEM;
+
+ cmdq->pdata = (struct gce_sec_plat *)pdev->dev.platform_data;
+ if (!cmdq->pdata) {
+ dev_err(dev, "no valid gce platform data!\n");
+ return -EINVAL;
+ }
+
+ gce_dev = cmdq->pdata->gce_dev;
+ cmdq->base = devm_platform_get_and_ioremap_resource(to_platform_device(gce_dev),
+ 0, &res);
+ if (IS_ERR(cmdq->base))
+ return PTR_ERR(cmdq->base);
+
+ cmdq->base_pa = res->start;
+
+ cmdq->mbox.dev = gce_dev;
+ cmdq->mbox.chans = devm_kcalloc(dev, cmdq->pdata->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->pdata->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->sec_thread = devm_kcalloc(dev, cmdq->pdata->thread_nr,
+ sizeof(*cmdq->sec_thread), GFP_KERNEL);
+ if (!cmdq->sec_thread)
+ return -ENOMEM;
+
+ mutex_init(&cmdq->exec_lock);
+ for (i = 0; i < cmdq->pdata->thread_nr; i++) {
+ cmdq->sec_thread[i].thread.base = cmdq->base + CMDQ_THR_BASE + CMDQ_THR_SIZE * i;
+ INIT_LIST_HEAD(&cmdq->sec_thread[i].thread.task_busy_list);
+ cmdq->sec_thread[i].idx = i;
+ cmdq->mbox.chans[i].con_priv = (void *)&cmdq->sec_thread[i].thread;
+ }
+
+ 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->pdata->gce_num, cmdq->pdata->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_ctx, &cmdq->context->iwc_msg);
+
+ mbox_controller_unregister(&cmdq->mbox);
+
+ clk_bulk_disable_unprepare(cmdq->pdata->gce_num, cmdq->pdata->clocks);
+ return 0;
+}
+
+static struct platform_driver cmdq_sec_drv = {
+ .probe = cmdq_sec_probe,
+ .remove = cmdq_sec_remove,
+ .driver = {
+ .name = "mtk-cmdq-sec",
+ .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;
+}
+
+rootfs_initcall(cmdq_sec_init);
+
+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 0000000000000..e3f5ba6aaaaad
--- /dev/null
+++ b/drivers/mailbox/mtk-cmdq-sec-tee.c
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#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);
+
+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_GPL(cmdq_sec_setup_tee_context);
+
+static int tee_dev_match(struct tee_ioctl_version_data *t, const void *v)
+{
+ if (t->impl_id == TEE_IMPL_ID_OPTEE)
+ return 1;
+
+ return 0;
+}
+
+int cmdq_sec_init_context(struct cmdq_sec_tee_context *tee)
+{
+ tee->tee_context = tee_client_open_context(NULL, tee_dev_match, NULL, NULL);
+ if (!tee->tee_context) {
+ pr_err("[%s][%d] tee_client_open_context failed!", __func__, __LINE__);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_init_context);
+
+int cmdq_sec_deinit_context(struct cmdq_sec_tee_context *tee)
+{
+ if (tee && tee->tee_context)
+ tee_client_close_context(tee->tee_context);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_deinit_context);
+
+int cmdq_sec_allocate_wsm(struct cmdq_sec_tee_context *tee, void **wsm_buffer, u32 size)
+{
+ void *buffer;
+
+ if (!wsm_buffer)
+ return -EINVAL;
+
+ if (size == 0)
+ return -EINVAL;
+
+ buffer = kmalloc(size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ tee->shared_mem = tee_shm_register_kernel_buf(tee->tee_context, buffer, size);
+ if (!tee->shared_mem) {
+ kfree(buffer);
+ return -ENOMEM;
+ }
+
+ *wsm_buffer = buffer;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_allocate_wsm);
+
+int cmdq_sec_free_wsm(struct cmdq_sec_tee_context *tee, void **wsm_buffer)
+{
+ if (!wsm_buffer)
+ return -EINVAL;
+
+ tee_shm_put(tee->shared_mem);
+ tee->shared_mem = NULL;
+ kfree(*wsm_buffer);
+ *wsm_buffer = NULL;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_free_wsm);
+
+int cmdq_sec_open_session(struct cmdq_sec_tee_context *tee, void *wsm_buffer)
+{
+ struct tee_ioctl_open_session_arg osarg = {0};
+ struct tee_param params = {0};
+ int ret = 0;
+
+ if (!wsm_buffer)
+ return -EINVAL;
+
+ osarg.num_params = 1;
+ memcpy(osarg.uuid, tee->uuid, sizeof(osarg.uuid));
+ osarg.clnt_login = 0;
+
+ ret = tee_client_open_session(tee->tee_context, &osarg, ¶ms);
+ if (ret)
+ return -EFAULT;
+
+ if (!osarg.ret)
+ tee->session = osarg.session;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_open_session);
+
+int cmdq_sec_close_session(struct cmdq_sec_tee_context *tee)
+{
+ tee_client_close_session(tee->tee_context, tee->session);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_close_session);
+
+int cmdq_sec_execute_session(struct cmdq_sec_tee_context *tee, u32 cmd, s32 timeout_ms)
+{
+ struct tee_ioctl_invoke_arg invoke_arg = {0};
+ struct tee_param params = {0};
+ u64 ts = sched_clock();
+ int ret = 0;
+
+ mutex_lock(&cmdq_sec_exec_lock);
+
+ params.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT;
+ params.u.memref.shm = tee->shared_mem;
+ params.u.memref.shm_offs = 0;
+ params.u.memref.size = tee->shared_mem->size;
+
+ invoke_arg.num_params = 1;
+ invoke_arg.session = tee->session;
+ invoke_arg.func = cmd;
+
+ ret = tee_client_invoke_func(tee->tee_context, &invoke_arg, ¶ms);
+ if (ret) {
+ pr_err("tee_client_invoke_func failed, ret=%d\n", ret);
+ return -EFAULT;
+ }
+
+ ret = invoke_arg.ret;
+
+ mutex_unlock(&cmdq_sec_exec_lock);
+
+ ts = div_u64(sched_clock() - ts, 1000000);
+
+ if (ret != 0)
+ pr_err("[SEC]execute: TEEC_InvokeCommand:%u ret:%d cost:%lluus", cmd, ret, ts);
+ else if (ts > timeout_ms)
+ pr_err("[SEC]execute: TEEC_InvokeCommand:%u ret:%d cost:%lluus", cmd, ret, ts);
+ else
+ pr_debug("[SEC]execute: TEEC_InvokeCommand:%u ret:%d cost:%lluus", cmd, ret, ts);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cmdq_sec_execute_session);
+
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h
index 43eae45a08c94..d29916d171109 100644
--- a/include/linux/mailbox/mtk-cmdq-mailbox.h
+++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
@@ -22,6 +22,7 @@
#define CMDQ_SUBSYS_SHIFT 16
#define CMDQ_OP_CODE_SHIFT 24
#define CMDQ_JUMP_PASS CMDQ_INST_SIZE
+#define CMDQ_EOC_CMD 0x4000000000000001ULL
#define CMDQ_WFE_UPDATE BIT(31)
#define CMDQ_WFE_UPDATE_VALUE BIT(16)
@@ -84,6 +85,7 @@ struct cmdq_pkt {
size_t buf_size; /* real buffer size */
void *cl;
bool loop;
+ void *sec_data;
};
struct cmdq_thread {
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 0000000000000..655185ea8a82c
--- /dev/null
+++ b/include/linux/mailbox/mtk-cmdq-sec-iwc-common.h
@@ -0,0 +1,385 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __CMDQ_SEC_IWC_COMMON_H__
+#define __CMDQ_SEC_IWC_COMMON_H__
+
+/**
+ * CMDQ_SEC_SHARED_THR_CNT_OFFSET - shared memory offset to store thread count.
+ */
+#define CMDQ_SEC_SHARED_THR_CNT_OFFSET 0x100
+
+/**
+ * CMDQ_TZ_CMD_BLOCK_SIZE - total command buffer size copy from normal world to secure world.
+ * maximum 20 pages may be requested for MDP readback.
+ */
+#define CMDQ_TZ_CMD_BLOCK_SIZE (20 << 12)
+
+/**
+ * CMDQ_IWC_MAX_CMD_LENGTH - max length of u32 array to store commanad buffer.
+ */
+#define CMDQ_IWC_MAX_CMD_LENGTH (CMDQ_TZ_CMD_BLOCK_SIZE / sizeof(u32))
+
+/**
+ * CMDQ_IWC_MAX_ADDR_LIST_LENGTH - max length of addr metadata list.
+ */
+#define CMDQ_IWC_MAX_ADDR_LIST_LENGTH (30)
+
+/**
+ * CMDQ_IWC_CLIENT_NAME - length for caller_name in iwc_cmdq_command_t.
+ */
+#define CMDQ_IWC_CLIENT_NAME (16)
+
+/**
+ * CMDQ_MAX_READBACK_ENG - length for readback_engs in iwc_cmdq_command_t.
+ */
+#define CMDQ_MAX_READBACK_ENG (8)
+
+/**
+ * CMDQ_SEC_MESSAGE_INST_LEN - length for sec_inst in iwc_cmdq_sec_status_t.
+ */
+#define CMDQ_SEC_MESSAGE_INST_LEN (8)
+
+/**
+ * CMDQ_SEC_DISPATCH_LEN - length for dispatch in iwc_cmdq_sec_status_t.
+ */
+#define CMDQ_SEC_DISPATCH_LEN (8)
+
+/*
+ * IWC Command IDs - ID for normal world(TLC or linux kernel) to secure world.
+ */
+#define CMD_CMDQ_IWC_SUBMIT_TASK (1) /* submit current task */
+#define CMD_CMDQ_IWC_CANCEL_TASK (3) /* cancel current task */
+#define CMD_CMDQ_IWC_PATH_RES_ALLOCATE (4) /* create global resource for secure path */
+
+/**
+ * enum cmdq_iwc_addr_metadata_type - address medadata type to be converted in secure world.
+ * @CMDQ_IWC_H_2_PA: secure handle to sec PA.
+ * @CMDQ_IWC_H_2_MVA: secure handle to sec MVA.
+ * @CMDQ_IWC_NMVA_2_MVA: map normal MVA to secure world.
+ * @CMDQ_IWC_PH_2_MVA: session protected handle to sec MVA.
+ *
+ * To tell secure world waht operation to use for converting address in metadata list.
+ */
+enum cmdq_iwc_addr_metadata_type {
+ CMDQ_IWC_H_2_PA = 0,
+ CMDQ_IWC_H_2_MVA = 1,
+ CMDQ_IWC_NMVA_2_MVA = 2,
+ CMDQ_IWC_PH_2_MVA = 3,
+};
+
+/*
+ * enum cmdq_sec_engine_enum - the flag for HW engines need to be proteced in secure world.
+ * Each enum is a bit in a u64 engine flag variable.
+ */
+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
+};
+
+/**
+ * struct iwc_cmdq_addr_metadata_t - metadata structure for converting address of secure buffer.
+ * @instr_idx: index of instruction.
+ * @type: addr metadata type.
+ * @base_handle: secure address handle.
+ * @block_offset: block offset from handle(PA) to current block(plane).
+ * @offset: buffser offset to secure handle.
+ * @size: buffer size.
+ * @port: HW port id (i.e. M4U port id)
+ */
+struct iwc_cmdq_addr_metadata_t {
+ /**
+ * @instr_idx: update its arg_b value to real PA/MVA in secure world.
+ */
+ u32 instr_idx;
+
+ /**
+ * @type: address medadata type to be converted in secure world.
+ */
+ u32 type;
+
+ /**
+ * @base_handle:
+ * @block_offset:
+ * @offset:
+ * @size:
+ * these members are used to store the buffer and offset relationship.
+ *
+ * -------------
+ * | | |
+ * -------------
+ * ^ ^ ^ ^
+ * A B C D
+ *
+ * A: base_handle
+ * B: base_handle + block_offset
+ * C: base_handle + block_offset + offset
+ * A~B or B~D: size
+ */
+ u64 base_handle;
+ u32 block_offset;
+ u32 offset;
+ u32 size;
+
+ /**
+ * @port: [IN]
+ *
+ * used to configure M4U port id.
+ */
+ u32 port;
+};
+
+/**
+ * struct iwc_cmdq_metadata_t - metadata structure for converting a list of secure buffer address.
+ * @addr_list_length: length of metadata address list.
+ * @addr_list: array of metadata address list.
+ * @engs_need_dapc: HW engines need to be protected by dapc.
+ * @engs_need_sec_port: HW engines need to be protected by secure larb port.
+ */
+struct iwc_cmdq_metadata_t {
+ u32 addr_list_length;
+ struct iwc_cmdq_addr_metadata_t addr_list[CMDQ_IWC_MAX_ADDR_LIST_LENGTH];
+ u64 engs_need_dapc;
+ u64 engs_need_sec_port;
+};
+
+/**
+ * enum sec_extension_iwc - extension HW engine flag to be protcted in secure world.
+ * @IWC_MDP_AAL: for MDP AAL engine.
+ * @IWC_MDP_TDSHP: for MDP TDSHP engine.
+ */
+enum sec_extension_iwc {
+ IWC_MDP_AAL = 0,
+ IWC_MDP_TDSHP,
+};
+
+/**
+ * struct readback_engine - readback engine parameters.
+ * @engine: HW engine flag for readback.
+ * @start: start address pa of readback buffer.
+ * @count: u32 size count of readback buffer.
+ * @param: other parameters need in secure world.
+ */
+struct readback_engine {
+ u32 engine;
+ u32 start;
+ u32 count;
+ u32 param;
+};
+
+/**
+ * struct iwc_cmdq_command_t - structure for excuting cmdq task in secure world.
+ * @thread: GCE secure thread index to execute command.
+ * @scenario: scenario to execute command.
+ * @priority: priority of GCE secure thread.
+ * @cmd_size: command size used in command buffer.
+ * @eng_flag: HW engine flag need to enable protection configuration.
+ * @va_base: command buffer
+ * @wait_cookie: index in thread's task list, it should be (nextCookie - 1).
+ * @reset_exec: reset HW thread.
+ * @caller_pid: pid of client module.
+ * @caller_name: name of client module.
+ * @metadata: metadata structure for converting a list of secure buffer address.
+ * @extension: extension HW engine flag to be protcted in secure world.
+ * @readback_pa: readback buffer pa.
+ * @normal_task_handle: handle to reference task in normal world.
+ * @mdp_extension: extension MDP HW engine flag to be protcted in secure world.
+ * @readback_engs: array of readback engines parameters.
+ * @readback_cnt: count of readback_engs array.
+ */
+struct iwc_cmdq_command_t {
+ /* basic execution data */
+ u32 thread;
+ u32 scenario;
+ u32 priority;
+ u32 cmd_size;
+ u64 eng_flag;
+ u32 va_base[CMDQ_IWC_MAX_CMD_LENGTH];
+
+ /* exec order data */
+ u32 wait_cookie;
+ bool reset_exec;
+
+ /* client info */
+ s32 caller_pid;
+ char caller_name[CMDQ_IWC_CLIENT_NAME];
+
+ /* metadata */
+ struct iwc_cmdq_metadata_t metadata;
+
+ /* client extension bits */
+ u64 extension;
+ u64 readback_pa;
+
+ /* debug */
+ u64 normal_task_handle;
+
+ /* SVP HDR */
+ u32 mdp_extension;
+ struct readback_engine readback_engs[CMDQ_MAX_READBACK_ENG];
+ u32 readback_cnt;
+};
+
+/**
+ * struct iwc_cmdq_cancel_task_t - structure for canceling cmdq task in the secure world.
+ * @thread: [IN] GCE secure thread index.
+ * @wait_cookie: [IN] execute count cookie to wait.
+ * @throw_aee: [OUT] AEE has thrown.
+ * @has_reset: [OUT] current secure thread has been reset
+ * @irq_status: [OUT] global secure IRQ flag.
+ * @irq_flag: [OUT] thread IRQ flag.
+ * @err_instr: [OUT] err_instr[0] = instruction low bits, err_instr[1] = instruction high bits.
+ * @reg_value: [OUT] value of error register.
+ * @pc: [OUT] current pc.
+ *
+ * used to allocate share memory from secure world.
+ */
+struct iwc_cmdq_cancel_task_t {
+ s32 thread;
+ u32 wait_cookie;
+ bool throw_aee;
+ bool has_reset;
+ s32 irq_status;
+ s32 irq_flag;
+ u32 err_instr[2];
+ u32 reg_value;
+ u32 pc;
+};
+
+/**
+ * struct iwc_cmdq_path_resource_t - Inter-World Communication resource allocation structure.
+ * @share_memoy_pa: use long long for 64 bit compatible support.
+ * @size: size of share memory.
+ * @use_normal_irq: use normal IRQ in secure world.
+ *
+ * used to allocate share memory from secure world.
+ */
+struct iwc_cmdq_path_resource_t {
+ long long share_memoy_pa;
+ u32 size;
+ bool use_normal_irq;
+};
+
+/**
+ * struct iwc_cmdq_debug_config_t - debug config structure for secure debug log.
+ *
+ * @log_level: log level in secure world.
+ * @enable_profile: enable profile in secure world.
+ */
+struct iwc_cmdq_debug_config_t {
+ s32 log_level;
+ s32 enable_profile;
+};
+
+/**
+ * struct iwc_cmdq_sec_status_t - secure status from secure world.
+ *
+ * @step: the step in secure cmdq TA.
+ * @status: the status in secure cmdq TA.
+ * @args: the status arguments in secure cmdq TA.
+ * @sec_inst: current instruction in secure cmdq TA.
+ * @inst_index: current instruction index in secure cmdq TA.
+ * @dispatch: current HW engine configuring in secure cmdq TA.
+ */
+struct iwc_cmdq_sec_status_t {
+ u32 step;
+ s32 status;
+ u32 args[4];
+ u32 sec_inst[CMDQ_SEC_MESSAGE_INST_LEN];
+ u32 inst_index;
+ char dispatch[CMDQ_SEC_DISPATCH_LEN];
+};
+
+/**
+ * struct iwc_cmdq_message_t - Inter-World Communication message structure.
+ * @cmd: [IN] iwc command id.
+ * @rsp: [OUT] respond from secureworld, 0 for success, < 0 for error.
+ * @command: [IN] structure for excuting cmdq task in secure world.
+ * @cancel_task: [IN] structure for canceling cmdq task in the secure world.
+ * @path_resource: [IN]
+ * @debug: [IN] debug config structure for secure debug log.
+ * @sec_status: [OUT] secure status from secure world.
+ * @cmdq_id: [IN] GCE core id.
+ *
+ * Both Linex kernel and mobicore have their own MMU tables for mapping
+ * world shared memory and physical addresses, so mobicore does not understand
+ * linux virtual address mapping.
+ * If we want to transact a large buffer in TCI/DCI, there are 2 ways (both require 1 copy):
+ * 1. Ue mc_map to map the normal world buffer to WSM and pass secure_virt_addr in TCI/DCI buffer.
+ * Note that mc_map implies a memcopy to copy the content from normal world to WSM.
+ * 2. Declare a fixed-length array in TCI/DCI struct and its size must be < 1M.
+ */
+struct iwc_cmdq_message_t {
+ union {
+ u32 cmd;
+ s32 rsp;
+ };
+
+ union {
+ struct iwc_cmdq_command_t command;
+ struct iwc_cmdq_cancel_task_t cancel_task;
+ struct iwc_cmdq_path_resource_t path_resource;
+ };
+
+ struct iwc_cmdq_debug_config_t debug;
+ struct iwc_cmdq_sec_status_t sec_status;
+
+ u8 cmdq_id;
+};
+#endif /* __CMDQ_SEC_IWC_COMMON_H__ */
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 0000000000000..01a842d713e63
--- /dev/null
+++ b/include/linux/mailbox/mtk-cmdq-sec-mailbox.h
@@ -0,0 +1,158 @@
+/* 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)
+
+/**
+ * CMDQ_MAX_COOKIE_VALUE - max value of CMDQ_THR_EXEC_CNT_PA (value starts from 0)
+ */
+#define CMDQ_MAX_COOKIE_VALUE (0xffff)
+
+/**
+ * enum cmdq_sec_scenario - scenario settings for cmdq TA.
+ * @CMDQ_SEC_SCNR_PRIMARY_DISP: primary display vdo mode enable.
+ * @CMDQ_SEC_SCNR_SUB_DISP: external display vdo mode enable.
+ * @CMDQ_SEC_SCNR_PRIMARY_DISP_DISABLE: primary display vdo mode disable.
+ * @CMDQ_SEC_SCNR_SUB_DISP_DISABLE: external display vdo mode disable.
+ * @CMDQ_SEC_SCNR_MAX: the end of enum.
+ *
+ * These states are used to record the state of IWC message structure.
+ */
+enum cmdq_sec_scenario {
+ CMDQ_SEC_SCNR_PRIMARY_DISP = 1,
+ CMDQ_SEC_SCNR_SUB_DISP = 4,
+ CMDQ_SEC_SCNR_PRIMARY_DISP_DISABLE = 18,
+ CMDQ_SEC_SCNR_SUB_DISP_DISABLE = 19,
+ CMDQ_SEC_SCNR_MAX,
+};
+
+/**
+ * enum cmdq_iwc_state_enum - state of Inter-world Communication(IWC) message
+ * @IWC_INIT: state of initializing tee context, means tee context has not initialized.
+ * @IWC_CONTEXT_INITED: tee context has initialized.
+ * @IWC_WSM_ALLOCATED: world share memory has allocated.
+ * @IWC_SES_OPENED: session to the tee context has opend.
+ * @IWC_SES_ON_TRANSACTED: session to the tee context has transacted.
+ * @IWC_STATE_MAX: the end of enum.
+ *
+ * These states are used to record the state of IWC message structure.
+ */
+enum cmdq_iwc_state_enum {
+ IWC_INIT,
+ IWC_CONTEXT_INITED,
+ IWC_WSM_ALLOCATED,
+ IWC_SES_OPENED,
+ IWC_SES_ON_TRANSACTED,
+ IWC_STATE_MAX,
+};
+
+/**
+ * struct gce_sec_plat - used to pass platform data from cmdq driver.
+ * @gce_dev: pointer to GCE device.
+ * @hwid: GCE core id.
+ * @gce_num: number of GCE core.
+ * @clocks: GCE clocks.
+ * @thread_nr: number of thread in each GCE core.
+ * @secure_thread_nr: number of secure thread.
+ * @secure_thread_min: min index of secure thread.
+ * @cmdq_event: secure EOF event id.
+ */
+struct gce_sec_plat {
+ struct device *gce_dev;
+ u32 hwid;
+ u32 gce_num;
+ struct clk_bulk_data *clocks;
+ u32 thread_nr;
+ u8 secure_thread_nr;
+ u8 secure_thread_min;
+ u32 cmdq_event;
+};
+
+/**
+ * struct cmdq_sec_data - used to translate secure buffer PA related instruction
+ * @addr_metadata_cnt: count of element in addr_list.
+ * @addr_metadatas: array of iwc_cmdq_addr_metadata_t.
+ * @addr_metadata_max_cnt: Reserved.
+ * @scenario: scenario config for secure world.
+ * @engs_need_dapc: engine falgs that need to config dapc in secure world.
+ * @engs_need_sec_port: engine falgs that need to config secure larb port in secure world.
+ * @response: return value from secure world.
+ * @sec_status: current iwc message status from secure world.
+ *
+ */
+struct cmdq_sec_data {
+ u32 addr_metadata_cnt;
+ u64 addr_metadatas;
+ u32 addr_metadata_max_cnt;
+ enum cmdq_sec_scenario scenario;
+ u64 engs_need_dapc;
+ u64 engs_need_sec_port;
+ s32 response;
+ struct iwc_cmdq_sec_status_t sec_status;
+};
+
+/**
+ * cmdq_sec_pkt_free_sec_data() - free sec_data for CMDQ packet.
+ * @pkt: the CMDQ packet.
+ */
+void cmdq_sec_pkt_free_sec_data(struct cmdq_pkt *pkt);
+
+/**
+ * cmdq_sec_pkt_alloc_sec_data() - allocate sec_data for CMDQ packet.
+ * @pkt: the CMDQ packet.
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_sec_pkt_alloc_sec_data(struct cmdq_pkt *pkt);
+
+/**
+ * cmdq_sec_insert_backup_cookie() - append backup cookie related instructions.
+ * @pkt: the CMDQ packet.
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+int cmdq_sec_insert_backup_cookie(struct cmdq_pkt *pkt);
+
+/**
+ * cmdq_sec_pkt_set_data() - set secure configuration to sec_data in CDMQ packet.
+ * @pkt: the CMDQ packet.
+ * @dapc_engine: the engine flag for dapc protection.
+ * @port_sec_engine: the engine flag for secure larb prot protection.
+ * @scenario: the scenario to CMDQ TA.
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+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);
+
+/**
+ * cmdq_sec_pkt_write() - append write secure buffer related instructions.
+ * @pkt: the CMDQ packet.
+ * @addr: the register to be configured.
+ * @base: the secure handle of secure buffer.
+ * @type: the address metadata conversion type.
+ * @offset: the address offset of secure buffer.
+ * @size: the secure buffer size.
+ * @port: the HW port id to M4U TA.
+ *
+ * Return: 0 for success; else the error code is returned
+ */
+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 0000000000000..d2c97a137e01f
--- /dev/null
+++ b/include/linux/mailbox/mtk-cmdq-sec-tee.h
@@ -0,0 +1,105 @@
+/* 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>
+
+/**
+ * struct cmdq_sec_tee_context - context for tee vendor
+ * @uuid: Universally Unique Identifier of secure world.
+ * @tee_context: basic tee context.
+ * @session: session handle.
+ * @shared_mem: shared memory.
+ */
+struct cmdq_sec_tee_context {
+ u8 uuid[TEE_IOCTL_UUID_LEN];
+ struct tee_context *tee_context;
+ u32 session;
+ struct tee_shm *shared_mem;
+};
+
+/**
+ * cmdq_sec_setup_tee_context() - setup the uuid for the tee context to communicate with
+ * @tee: context for tee vendor
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+void cmdq_sec_setup_tee_context(struct cmdq_sec_tee_context *tee);
+
+/**
+ * cmdq_sec_init_context() - initialize the tee context
+ * @tee: context for tee vendor
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_init_context(struct cmdq_sec_tee_context *tee);
+
+/**
+ * cmdq_sec_deinit_context() - de-initialize the tee context
+ * @tee: context for tee vendor
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_deinit_context(struct cmdq_sec_tee_context *tee);
+
+/**
+ * cmdq_sec_allocate_wsm() - allocate the world share memory to pass message to tee
+ * @tee: context for tee vendor
+ * @wsm_buffer: world share memory buffer with parameters pass to tee
+ * @size: size to allocate
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_allocate_wsm(struct cmdq_sec_tee_context *tee, void **wsm_buffer, u32 size);
+
+/**
+ * cmdq_sec_free_wsm() - free the world share memory
+ * @tee: context for tee vendor
+ * @wsm_buffer: world share memory buffer with parameters pass to tee
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_free_wsm(struct cmdq_sec_tee_context *tee, void **wsm_buffer);
+
+/**
+ * cmdq_sec_open_session() - open session to the tee context
+ * @tee: context for tee vendor
+ * @wsm_buffer: world share memory buffer with parameters pass to tee
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_open_session(struct cmdq_sec_tee_context *tee, void *wsm_buffer);
+
+/**
+ * cmdq_sec_close_session() - close session to the tee context
+ * @tee: context for tee vendor
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_close_session(struct cmdq_sec_tee_context *tee);
+
+/**
+ * cmdq_sec_execute_session() - execute session to the tee context
+ * @tee: context for tee vendor
+ * @cmd: tee invoke cmd id
+ * @timeout_ms: timeout ms to current tee invoke cmd
+ *
+ * Return: 0 for success; else the error code is returned
+ *
+ */
+int cmdq_sec_execute_session(struct cmdq_sec_tee_context *tee, u32 cmd, s32 timeout_ms);
+
+#endif /* __MTK_CMDQ_SEC_TEE_H__ */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 0/9] Add CMDQ secure driver for SVP
From: Shawn Sung @ 2024-04-03 6:55 UTC (permalink / raw)
To: CK Hu, Jassi Brar, AngeloGioacchino Del Regno
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
Hsiao Chien Sung, Jason-JH . Lin, Houlong Wei, linux-kernel,
devicetree, linux-arm-kernel, linux-mediatek, Hsiao Chien Sung
From: Hsiao Chien Sung <shawn.sung@mediatek.corp-partner.google.com>
For the Secure Video Path (SVP) feature, inculding the memory stored
secure video content, the registers of display HW pipeline and the
HW configure operations are required to execute in the secure world.
So using a CMDQ secure driver to make all display HW registers
configuration secure DRAM access permision settings execute by GCE
secure thread in the secure world.
We are landing this feature on mt8188 and mt8195 currently.
---
Based on 2 series and 1 patch:
[1] Add CMDQ driver support for mt8188
- https://patchwork.kernel.org/project/linux-mediatek/list/?series=810382
[2] Add mediatek,gce-events definition to mediatek,gce-mailbox bindings
- https://patchwork.kernel.org/project/linux-mediatek/list/?series=810938
[3] soc: mediatek: Add register definitions for GCE
- https://patchwork.kernel.org/project/linux-mediatek/patch/20231017064717.21616-2-shawn.sung@mediatek.com/
---
Changes in v4:
1. Rebase on mediatek-drm-next(278640d4d74cd) and fix the conflicts
2. This series is based on 20240307013458.23550-1-jason-jh.lin@mediatek.com
Changes in v3:
1. separate mt8188 driver porting patches to another series
2. separate adding 'mediatek,gce-events' event prop to another series
3. sepatate mailbox helper and controller driver modification to a
single patch for adding looping thread
4. add kerneldoc for secure mailbox related definition
5. add moving reuseable definition patch before adding secure mailbox
driver patch
6. adjust redundant logic in mtk-cmdq-sec-mailbox
Changes in v2:
1. adjust dt-binding SW event define patch before the dt-binding patch using it
2. adjust dt-binding patch for secure cmdq driver
3. remove the redundant patches or merge the patches of modification for the same API
Jason-JH.Lin (9):
dt-bindings: gce: mt8195: Add CMDQ_SYNC_TOKEN_SECURE_THR_EOF event id
dt-bindings: mailbox: Add mboxes property for CMDQ secure driver
soc: mediatek: cmdq: Add cmdq_pkt_logic_command to support math
operation
soc: mediatek: cmdq: Add cmdq_pkt_write_s_reg_value to support write
value to reg
mailbox: mtk-cmdq: Support GCE loop packets in interrupt handler
mediatek: cmdq: Add cmdq_pkt_finalize_loop for looping cmd with irq
mailbox: mediatek: Move reuseable definition to header for secure
driver
mailbox: mediatek: Add CMDQ secure mailbox driver
mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver
.../mailbox/mediatek,gce-mailbox.yaml | 3 +
drivers/mailbox/Makefile | 2 +-
drivers/mailbox/mtk-cmdq-mailbox.c | 79 +-
drivers/mailbox/mtk-cmdq-sec-mailbox.c | 1091 +++++++++++++++++
drivers/mailbox/mtk-cmdq-sec-tee.c | 165 +++
drivers/soc/mediatek/mtk-cmdq-helper.c | 72 ++
include/dt-bindings/gce/mt8195-gce.h | 6 +
include/linux/mailbox/mtk-cmdq-mailbox.h | 36 +
.../linux/mailbox/mtk-cmdq-sec-iwc-common.h | 385 ++++++
include/linux/mailbox/mtk-cmdq-sec-mailbox.h | 158 +++
include/linux/mailbox/mtk-cmdq-sec-tee.h | 105 ++
include/linux/soc/mediatek/mtk-cmdq.h | 61 +
12 files changed, 2132 insertions(+), 31 deletions(-)
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
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v4 9/9] mailbox: mediatek: Add secure CMDQ driver support for CMDQ driver
From: Shawn Sung @ 2024-04-03 6:56 UTC (permalink / raw)
To: CK Hu, Jassi Brar, AngeloGioacchino Del Regno
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
Hsiao Chien Sung, Jason-JH . Lin, Houlong Wei, linux-kernel,
devicetree, linux-arm-kernel, linux-mediatek
In-Reply-To: <20240403065603.21920-1-shawn.sung@mediatek.com>
From: "Jason-JH.Lin" <jason-jh.lin@mediatek.com>
CMDQ driver will probe a secure CMDQ driver when has_sec flag
in platform data is true and its device node in dts has defined a
event id of CMDQ_SYNC_TOKEN_SEC_EOF.
Secure CMDQ driver support on mt8188 and mt8195 currently.
So add a has_secure flag to their driver data to probe it.
Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
drivers/mailbox/mtk-cmdq-mailbox.c | 38 ++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index e04302ca6ec03..a8a0619baaa5c 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -15,6 +15,7 @@
#include <linux/pm_runtime.h>
#include <linux/mailbox_controller.h>
#include <linux/mailbox/mtk-cmdq-mailbox.h>
+#include <linux/mailbox/mtk-cmdq-sec-mailbox.h>
#include <linux/of.h>
#define CMDQ_MBOX_AUTOSUSPEND_DELAY_MS 100
@@ -60,6 +61,9 @@ struct gce_plat {
u8 shift;
bool control_by_sw;
bool sw_ddr_en;
+ bool has_secure;
+ u32 secure_thread_nr;
+ u32 secure_thread_min;
u32 gce_num;
};
@@ -569,6 +573,7 @@ static int cmdq_probe(struct platform_device *pdev)
int alias_id = 0;
static const char * const clk_name = "gce";
static const char * const clk_names[] = { "gce0", "gce1" };
+ u32 hwid = 0;
cmdq = devm_kzalloc(dev, sizeof(*cmdq), GFP_KERNEL);
if (!cmdq)
@@ -594,6 +599,8 @@ static int cmdq_probe(struct platform_device *pdev)
dev, cmdq->base, cmdq->irq);
if (cmdq->pdata->gce_num > 1) {
+ hwid = of_alias_get_id(dev->of_node, clk_name);
+
for_each_child_of_node(phandle->parent, node) {
alias_id = of_alias_get_id(node, clk_name);
if (alias_id >= 0 && alias_id < cmdq->pdata->gce_num) {
@@ -676,6 +683,31 @@ static int cmdq_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(dev, CMDQ_MBOX_AUTOSUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
+ if (cmdq->pdata->has_secure) {
+ struct platform_device *mtk_cmdq_sec;
+ static struct gce_sec_plat sec_plat = {0};
+
+ if (of_property_read_u32_index(dev->of_node, "mediatek,gce-events", 0,
+ &sec_plat.cmdq_event) == 0) {
+ sec_plat.gce_dev = dev;
+ sec_plat.hwid = hwid;
+ sec_plat.gce_num = cmdq->pdata->gce_num;
+ sec_plat.clocks = cmdq->clocks;
+ sec_plat.thread_nr = cmdq->pdata->thread_nr;
+ sec_plat.secure_thread_nr = cmdq->pdata->secure_thread_nr;
+ sec_plat.secure_thread_min = cmdq->pdata->secure_thread_min;
+
+ mtk_cmdq_sec = platform_device_register_data(dev, "mtk-cmdq-sec",
+ PLATFORM_DEVID_AUTO,
+ &sec_plat,
+ sizeof(sec_plat));
+ if (IS_ERR(mtk_cmdq_sec)) {
+ dev_err(dev, "failed to register platform_device mtk-cmdq-sec\n");
+ return PTR_ERR(mtk_cmdq_sec);
+ }
+ }
+ }
+
return 0;
}
@@ -719,6 +751,9 @@ static const struct gce_plat gce_plat_mt8188 = {
.thread_nr = 32,
.shift = 3,
.control_by_sw = true,
+ .has_secure = true,
+ .secure_thread_nr = 2,
+ .secure_thread_min = 8,
.gce_num = 2
};
@@ -733,6 +768,9 @@ static const struct gce_plat gce_plat_mt8195 = {
.thread_nr = 24,
.shift = 3,
.control_by_sw = true,
+ .has_secure = true,
+ .secure_thread_nr = 2,
+ .secure_thread_min = 8,
.gce_num = 2
};
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4 7/9] mailbox: mediatek: Move reuseable definition to header for secure driver
From: Shawn Sung @ 2024-04-03 6:56 UTC (permalink / raw)
To: CK Hu, Jassi Brar, AngeloGioacchino Del Regno
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
Hsiao Chien Sung, Jason-JH . Lin, Houlong Wei, linux-kernel,
devicetree, linux-arm-kernel, linux-mediatek
In-Reply-To: <20240403065603.21920-1-shawn.sung@mediatek.com>
From: "Jason-JH.Lin" <jason-jh.lin@mediatek.com>
To support CMDQ secure driver, move some reuseable definition to header.
- define: e.g. CMDQ_GCE_NUM_MAX, CMDQ_THR_BASE, CMDQ_THR_SIZE.
- struct: e.g. cmdq_thread, cmdq, cmdq_task.
- include: e.g. <linux/clk.h>.
Add "#include <linux/mailbox_controller.h>" for the function that takes
"struct mbox_chan * chan" as a parameter. That may occur a build error
if secure driver header includes the mtk-cmdq-mailbox.h.
- function: e.g. cmdq_get_shift_pa(struct mbox_chan *chan).
Signed-off-by: Jason-JH.Lin <jason-jh.lin@mediatek.com>
Signed-off-by: Hsiao Chien Sung <shawn.sung@mediatek.com>
---
drivers/mailbox/mtk-cmdq-mailbox.c | 30 ---------------------
include/linux/mailbox/mtk-cmdq-mailbox.h | 33 ++++++++++++++++++++++++
2 files changed, 33 insertions(+), 30 deletions(-)
diff --git a/drivers/mailbox/mtk-cmdq-mailbox.c b/drivers/mailbox/mtk-cmdq-mailbox.c
index 5906e0343d1fc..e04302ca6ec03 100644
--- a/drivers/mailbox/mtk-cmdq-mailbox.c
+++ b/drivers/mailbox/mtk-cmdq-mailbox.c
@@ -3,7 +3,6 @@
// Copyright (c) 2018 MediaTek Inc.
#include <linux/bitops.h>
-#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/dma-mapping.h>
#include <linux/errno.h>
@@ -22,13 +21,10 @@
#define CMDQ_OP_CODE_MASK (0xff << CMDQ_OP_CODE_SHIFT)
#define CMDQ_NUM_CMD(t) (t->cmd_buf_size / CMDQ_INST_SIZE)
-#define CMDQ_GCE_NUM_MAX (2)
#define CMDQ_CURR_IRQ_STATUS 0x10
#define CMDQ_SYNC_TOKEN_UPDATE 0x68
#define CMDQ_THR_SLOT_CYCLES 0x30
-#define CMDQ_THR_BASE 0x100
-#define CMDQ_THR_SIZE 0x80
#define CMDQ_THR_WARM_RESET 0x00
#define CMDQ_THR_ENABLE_TASK 0x04
#define CMDQ_THR_SUSPEND_TASK 0x08
@@ -59,32 +55,6 @@
#define CMDQ_JUMP_BY_OFFSET 0x10000000
#define CMDQ_JUMP_BY_PA 0x10000001
-struct cmdq_thread {
- struct mbox_chan *chan;
- void __iomem *base;
- struct list_head task_busy_list;
- u32 priority;
-};
-
-struct cmdq_task {
- struct cmdq *cmdq;
- struct list_head list_entry;
- dma_addr_t pa_base;
- struct cmdq_thread *thread;
- struct cmdq_pkt *pkt; /* the packet sent from mailbox client */
-};
-
-struct cmdq {
- struct mbox_controller mbox;
- void __iomem *base;
- int irq;
- u32 irq_mask;
- const struct gce_plat *pdata;
- struct cmdq_thread *thread;
- struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX];
- bool suspended;
-};
-
struct gce_plat {
u32 thread_nr;
u8 shift;
diff --git a/include/linux/mailbox/mtk-cmdq-mailbox.h b/include/linux/mailbox/mtk-cmdq-mailbox.h
index f78a08e7c6ede..43eae45a08c94 100644
--- a/include/linux/mailbox/mtk-cmdq-mailbox.h
+++ b/include/linux/mailbox/mtk-cmdq-mailbox.h
@@ -7,10 +7,17 @@
#ifndef __MTK_CMDQ_MAILBOX_H__
#define __MTK_CMDQ_MAILBOX_H__
+#include <linux/clk.h>
+#include <linux/mailbox_controller.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
+#define CMDQ_GCE_NUM_MAX 2
+
+#define CMDQ_THR_BASE 0x100
+#define CMDQ_THR_SIZE 0x80
+
#define CMDQ_INST_SIZE 8 /* instruction is 64-bit */
#define CMDQ_SUBSYS_SHIFT 16
#define CMDQ_OP_CODE_SHIFT 24
@@ -79,6 +86,32 @@ struct cmdq_pkt {
bool loop;
};
+struct cmdq_thread {
+ struct mbox_chan *chan;
+ void __iomem *base;
+ struct list_head task_busy_list;
+ u32 priority;
+};
+
+struct cmdq {
+ struct mbox_controller mbox;
+ void __iomem *base;
+ int irq;
+ u32 irq_mask;
+ const struct gce_plat *pdata;
+ struct cmdq_thread *thread;
+ struct clk_bulk_data clocks[CMDQ_GCE_NUM_MAX];
+ bool suspended;
+};
+
+struct cmdq_task {
+ struct cmdq *cmdq;
+ struct list_head list_entry;
+ dma_addr_t pa_base;
+ struct cmdq_thread *thread;
+ struct cmdq_pkt *pkt; /* the packet sent from mailbox client */
+};
+
u8 cmdq_get_shift_pa(struct mbox_chan *chan);
#endif /* __MTK_CMDQ_MAILBOX_H__ */
--
2.18.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH] arm64: tlb: Fix TLBI RANGE operand
From: Gavin Shan @ 2024-04-03 6:49 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, catalin.marinas, will, akpm, maz, apopple,
mark.rutland, ryan.roberts, rananta, yangyicong, v-songbaohua,
yezhenyu2, yihyu, shan.gavin
KVM/arm64 relies on TLBI RANGE feature to flush TLBs when the dirty
bitmap is collected by VMM and the corresponding PTEs need to be
write-protected again. Unfortunately, the operand passed to the TLBI
RANGE instruction isn't correctly sorted out by commit d1d3aa98b1d4
("arm64: tlb: Use the TLBI RANGE feature in arm64"). It leads to
crash on the destination VM after live migration because some of the
dirty pages are missed.
For example, I have a VM where 8GB memory is assigned, starting from
0x40000000 (1GB). Note that the host has 4KB as the base page size.
All TLBs for VM can be covered by one TLBI RANGE operation. However,
I receives 0xffff708000040000 as the operand, which is wrong and the
correct one should be 0x00007f8000040000. From the wrong operand, we
have 3 and 1 for SCALE (bits[45:44) and NUM (bits943:39], only 1GB
instead of 8GB memory is covered.
Fix the macro __TLBI_RANGE_NUM() so that the correct NUM and TLBI
RANGE operand are provided.
Fixes: d1d3aa98b1d4 ("arm64: tlb: Use the TLBI RANGE feature in arm64")
Cc: stable@kernel.org # v5.10+
Reported-by: Yihuang Yu <yihyu@redhat.com>
Signed-off-by: Gavin Shan <gshan@redhat.com>
---
arch/arm64/include/asm/tlbflush.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 3b0e8248e1a4..07c4fb4b82b4 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -166,7 +166,7 @@ static inline unsigned long get_trans_granule(void)
*/
#define TLBI_RANGE_MASK GENMASK_ULL(4, 0)
#define __TLBI_RANGE_NUM(pages, scale) \
- ((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1)
+ ((((pages) >> (5 * (scale) + 1)) - 1) & TLBI_RANGE_MASK)
/*
* TLB Invalidation
--
2.44.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v4] perf/marvell: Marvell PEM performance monitor support
From: Gowthami Thiagarajan @ 2024-04-03 5:41 UTC (permalink / raw)
To: will, mark.rutland, linux-arm-kernel, linux-kernel
Cc: sgoutham, gcherian, lcherian, Gowthami Thiagarajan
PCI Express Interface PMU includes various performance counters
to monitor the data that is transmitted over the PCIe link. The
counters track various inbound and outbound transactions which
includes separate counters for posted/non-posted/completion TLPs.
Also, inbound and outbound memory read requests along with their
latencies can also be monitored. Address Translation Services(ATS)events
such as ATS Translation, ATS Page Request, ATS Invalidation along with
their corresponding latencies are also supported.
The performance counters are 64 bits wide.
For instance,
perf stat -e ib_tlp_pr <workload>
tracks the inbound posted TLPs for the workload.
Signed-off-by: Gowthami Thiagarajan <gthiagarajan@marvell.com>
---
MAINTAINERS | 6 +
drivers/perf/Kconfig | 7 +
drivers/perf/Makefile | 1 +
drivers/perf/marvell_pem_pmu.c | 425 +++++++++++++++++++++++++++++++++
include/linux/cpuhotplug.h | 1 +
5 files changed, 440 insertions(+)
create mode 100644 drivers/perf/marvell_pem_pmu.c
diff --git a/MAINTAINERS b/MAINTAINERS
index dd5de540ec0b..50c11e128a98 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12759,6 +12759,12 @@ S: Supported
F: Documentation/networking/device_drivers/ethernet/marvell/octeontx2.rst
F: drivers/net/ethernet/marvell/octeontx2/af/
+MARVELL PEM PMU DRIVER
+M: Linu Cherian <lcherian@marvell.com>
+M: Gowthami Thiagarajan <gthiagarajan@marvell.com>
+S: Supported
+F: drivers/perf/marvell_pem_pmu.c
+
MARVELL PRESTERA ETHERNET SWITCH DRIVER
M: Taras Chornyi <taras.chornyi@plvision.eu>
S: Supported
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig
index 273d67ecf6d2..12ac8409263a 100644
--- a/drivers/perf/Kconfig
+++ b/drivers/perf/Kconfig
@@ -234,4 +234,11 @@ config CXL_PMU
If unsure say 'm'.
+config MARVELL_PEM_PMU
+ tristate "MARVELL PEM PMU Support"
+ depends on ARCH_THUNDER || (COMPILE_TEST && 64BIT)
+ help
+ Enable support for PCIe Interface performance monitoring
+ on Marvell platform.
+
endmenu
diff --git a/drivers/perf/Makefile b/drivers/perf/Makefile
index 16b3ec4db916..db3c473cc5c7 100644
--- a/drivers/perf/Makefile
+++ b/drivers/perf/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_ARM_SPE_PMU) += arm_spe_pmu.o
obj-$(CONFIG_ARM_DMC620_PMU) += arm_dmc620_pmu.o
obj-$(CONFIG_MARVELL_CN10K_TAD_PMU) += marvell_cn10k_tad_pmu.o
obj-$(CONFIG_MARVELL_CN10K_DDR_PMU) += marvell_cn10k_ddr_pmu.o
+obj-$(CONFIG_MARVELL_PEM_PMU) += marvell_pem_pmu.o
obj-$(CONFIG_APPLE_M1_CPU_PMU) += apple_m1_cpu_pmu.o
obj-$(CONFIG_ALIBABA_UNCORE_DRW_PMU) += alibaba_uncore_drw_pmu.o
obj-$(CONFIG_ARM_CORESIGHT_PMU_ARCH_SYSTEM_PMU) += arm_cspmu/
diff --git a/drivers/perf/marvell_pem_pmu.c b/drivers/perf/marvell_pem_pmu.c
new file mode 100644
index 000000000000..913175954a9c
--- /dev/null
+++ b/drivers/perf/marvell_pem_pmu.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Marvell PEM(PCIe RC) Performance Monitor Driver
+ *
+ * Copyright (C) 2024 Marvell.
+ */
+
+#include <linux/acpi.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+
+/*
+ * Each of these events maps to a free running 64 bit counter
+ * with no event control, but can be reset.
+ *
+ */
+enum pem_events {
+ IB_TLP_NPR,
+ IB_TLP_PR,
+ IB_TLP_CPL,
+ IB_TLP_DWORDS_NPR,
+ IB_TLP_DWORDS_PR,
+ IB_TLP_DWORDS_CPL,
+ IB_INFLIGHT,
+ IB_READS,
+ IB_REQ_NO_RO_NCB,
+ IB_REQ_NO_RO_EBUS,
+ OB_TLP_NPR,
+ OB_TLP_PR,
+ OB_TLP_CPL,
+ OB_TLP_DWORDS_NPR,
+ OB_TLP_DWORDS_PR,
+ OB_TLP_DWORDS_CPL,
+ OB_INFLIGHT,
+ OB_READS,
+ OB_MERGES_NPR,
+ OB_MERGES_PR,
+ OB_MERGES_CPL,
+ ATS_TRANS,
+ ATS_TRANS_LATENCY,
+ ATS_PRI,
+ ATS_PRI_LATENCY,
+ ATS_INV,
+ ATS_INV_LATENCY,
+ PEM_EVENTIDS_MAX,
+};
+
+static u64 eventid_to_offset_table[] = {
+ [IB_TLP_NPR] = 0x0,
+ [IB_TLP_PR] = 0x8,
+ [IB_TLP_CPL] = 0x10,
+ [IB_TLP_DWORDS_NPR] = 0x100,
+ [IB_TLP_DWORDS_PR] = 0x108,
+ [IB_TLP_DWORDS_CPL] = 0x110,
+ [IB_INFLIGHT] = 0x200,
+ [IB_READS] = 0x300,
+ [IB_REQ_NO_RO_NCB] = 0x400,
+ [IB_REQ_NO_RO_EBUS] = 0x408,
+ [OB_TLP_NPR] = 0x500,
+ [OB_TLP_PR] = 0x508,
+ [OB_TLP_CPL] = 0x510,
+ [OB_TLP_DWORDS_NPR] = 0x600,
+ [OB_TLP_DWORDS_PR] = 0x608,
+ [OB_TLP_DWORDS_CPL] = 0x610,
+ [OB_INFLIGHT] = 0x700,
+ [OB_READS] = 0x800,
+ [OB_MERGES_NPR] = 0x900,
+ [OB_MERGES_PR] = 0x908,
+ [OB_MERGES_CPL] = 0x910,
+ [ATS_TRANS] = 0x2D18,
+ [ATS_TRANS_LATENCY] = 0x2D20,
+ [ATS_PRI] = 0x2D28,
+ [ATS_PRI_LATENCY] = 0x2D30,
+ [ATS_INV] = 0x2D38,
+ [ATS_INV_LATENCY] = 0x2D40,
+};
+
+struct pem_pmu {
+ struct pmu pmu;
+ void __iomem *base;
+ unsigned int cpu;
+ struct device *dev;
+ struct hlist_node node;
+};
+
+#define to_pem_pmu(p) container_of(p, struct pem_pmu, pmu)
+
+static int eventid_to_offset(int eventid)
+{
+ return eventid_to_offset_table[eventid];
+}
+
+/* Events */
+static ssize_t pem_pmu_event_show(struct device *dev,
+ struct device_attribute *attr,
+ char *page)
+{
+ struct perf_pmu_events_attr *pmu_attr;
+
+ pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
+}
+
+#define PEM_EVENT_ATTR(_name, _id) \
+ (&((struct perf_pmu_events_attr[]) { \
+ { .attr = __ATTR(_name, 0444, pem_pmu_event_show, NULL), \
+ .id = _id, } \
+ })[0].attr.attr)
+
+static struct attribute *pem_perf_events_attrs[] = {
+ PEM_EVENT_ATTR(ib_tlp_npr, IB_TLP_NPR),
+ PEM_EVENT_ATTR(ib_tlp_pr, IB_TLP_PR),
+ PEM_EVENT_ATTR(ib_tlp_cpl_partid, IB_TLP_CPL),
+ PEM_EVENT_ATTR(ib_tlp_dwords_npr, IB_TLP_DWORDS_NPR),
+ PEM_EVENT_ATTR(ib_tlp_dwords_pr, IB_TLP_DWORDS_PR),
+ PEM_EVENT_ATTR(ib_tlp_dwords_cpl_partid, IB_TLP_DWORDS_CPL),
+ PEM_EVENT_ATTR(ib_inflight, IB_INFLIGHT),
+ PEM_EVENT_ATTR(ib_reads, IB_READS),
+ PEM_EVENT_ATTR(ib_req_no_ro_ncb, IB_REQ_NO_RO_NCB),
+ PEM_EVENT_ATTR(ib_req_no_ro_ebus, IB_REQ_NO_RO_EBUS),
+ PEM_EVENT_ATTR(ob_tlp_npr_partid, OB_TLP_NPR),
+ PEM_EVENT_ATTR(ob_tlp_pr_partid, OB_TLP_PR),
+ PEM_EVENT_ATTR(ob_tlp_cpl_partid, OB_TLP_CPL),
+ PEM_EVENT_ATTR(ob_tlp_dwords_npr_partid, OB_TLP_DWORDS_NPR),
+ PEM_EVENT_ATTR(ob_tlp_dwords_pr_partid, OB_TLP_DWORDS_PR),
+ PEM_EVENT_ATTR(ob_tlp_dwords_cpl_partid, OB_TLP_DWORDS_CPL),
+ PEM_EVENT_ATTR(ob_inflight_partid, OB_INFLIGHT),
+ PEM_EVENT_ATTR(ob_reads_partid, OB_READS),
+ PEM_EVENT_ATTR(ob_merges_npr_partid, OB_MERGES_NPR),
+ PEM_EVENT_ATTR(ob_merges_pr_partid, OB_MERGES_PR),
+ PEM_EVENT_ATTR(ob_merges_cpl_partid, OB_MERGES_CPL),
+ PEM_EVENT_ATTR(ats_trans, ATS_TRANS),
+ PEM_EVENT_ATTR(ats_trans_latency, ATS_TRANS_LATENCY),
+ PEM_EVENT_ATTR(ats_pri, ATS_PRI),
+ PEM_EVENT_ATTR(ats_pri_latency, ATS_PRI_LATENCY),
+ PEM_EVENT_ATTR(ats_inv, ATS_INV),
+ PEM_EVENT_ATTR(ats_inv_latency, ATS_INV_LATENCY),
+ NULL
+};
+
+static struct attribute_group pem_perf_events_attr_group = {
+ .name = "events",
+ .attrs = pem_perf_events_attrs,
+};
+
+PMU_FORMAT_ATTR(event, "config:0-5");
+
+static struct attribute *pem_perf_format_attrs[] = {
+ &format_attr_event.attr,
+ NULL
+};
+
+static struct attribute_group pem_perf_format_attr_group = {
+ .name = "format",
+ .attrs = pem_perf_format_attrs,
+};
+
+/* cpumask */
+static ssize_t pem_perf_cpumask_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pem_pmu *pmu = dev_get_drvdata(dev);
+
+ return cpumap_print_to_pagebuf(true, buf, cpumask_of(pmu->cpu));
+}
+
+static struct device_attribute pem_perf_cpumask_attr =
+ __ATTR(cpumask, 0444, pem_perf_cpumask_show, NULL);
+
+static struct attribute *pem_perf_cpumask_attrs[] = {
+ &pem_perf_cpumask_attr.attr,
+ NULL
+};
+
+static struct attribute_group pem_perf_cpumask_attr_group = {
+ .attrs = pem_perf_cpumask_attrs,
+};
+
+static const struct attribute_group *pem_perf_attr_groups[] = {
+ &pem_perf_events_attr_group,
+ &pem_perf_cpumask_attr_group,
+ &pem_perf_format_attr_group,
+ NULL
+};
+
+static int pem_perf_event_init(struct perf_event *event)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (event->attr.type != event->pmu->type)
+ return -ENOENT;
+
+ if (is_sampling_event(event) ||
+ event->attach_state & PERF_ATTACH_TASK) {
+ return -EOPNOTSUPP;
+ }
+
+ if (event->cpu < 0)
+ return -EOPNOTSUPP;
+
+ /* We must NOT create groups containing mixed PMUs */
+ if (event->group_leader->pmu != event->pmu &&
+ !is_software_event(event->group_leader))
+ return -EINVAL;
+
+ /*
+ * Set ownership of event to one CPU, same event can not be observed
+ * on multiple cpus at same time.
+ */
+ event->cpu = pmu->cpu;
+ hwc->idx = -1;
+ return 0;
+}
+
+static void pem_perf_counter_reset(struct pem_pmu *pmu,
+ struct perf_event *event, int eventid)
+{
+ writeq_relaxed(0x0, pmu->base + eventid_to_offset(eventid));
+}
+
+static u64 pem_perf_read_counter(struct pem_pmu *pmu,
+ struct perf_event *event, int eventid)
+{
+ return readq_relaxed(pmu->base + eventid_to_offset(eventid));
+}
+
+static void pem_perf_event_update(struct perf_event *event)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ u64 prev_count, new_count;
+
+ do {
+ prev_count = local64_read(&hwc->prev_count);
+ new_count = pem_perf_read_counter(pmu, event, hwc->idx);
+ } while (local64_xchg(&hwc->prev_count, new_count) != prev_count);
+
+ local64_add((new_count - prev_count), &event->count);
+}
+
+static void pem_perf_event_start(struct perf_event *event, int flags)
+{
+ struct pem_pmu *pmu = to_pem_pmu(event->pmu);
+ struct hw_perf_event *hwc = &event->hw;
+ int eventid = hwc->idx;
+
+ local64_set(&hwc->prev_count, 0);
+
+ pem_perf_counter_reset(pmu, event, eventid);
+
+ hwc->state = 0;
+}
+
+static int pem_perf_event_add(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ hwc->idx = event->attr.config;
+ if (hwc->idx >= PEM_EVENTIDS_MAX)
+ return -EINVAL;
+ hwc->state |= PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ pem_perf_event_start(event, flags);
+
+ return 0;
+}
+
+static void pem_perf_event_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (flags & PERF_EF_UPDATE)
+ pem_perf_event_update(event);
+
+ hwc->state |= PERF_HES_STOPPED;
+}
+
+static void pem_perf_event_del(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ pem_perf_event_stop(event, PERF_EF_UPDATE);
+ hwc->idx = -1;
+}
+
+static int pem_pmu_offline_cpu(unsigned int cpu, struct hlist_node *node)
+{
+ struct pem_pmu *pmu = hlist_entry_safe(node, struct pem_pmu,
+ node);
+ unsigned int target;
+
+ if (cpu != pmu->cpu)
+ return 0;
+
+ target = cpumask_any_but(cpu_online_mask, cpu);
+ if (target >= nr_cpu_ids)
+ return 0;
+
+ perf_pmu_migrate_context(&pmu->pmu, cpu, target);
+ pmu->cpu = target;
+ return 0;
+}
+
+static int pem_perf_probe(struct platform_device *pdev)
+{
+ struct pem_pmu *pem_pmu;
+ struct resource *res;
+ void __iomem *base;
+ char *name;
+ int ret;
+
+ pem_pmu = devm_kzalloc(&pdev->dev, sizeof(*pem_pmu), GFP_KERNEL);
+ if (!pem_pmu)
+ return -ENOMEM;
+
+ pem_pmu->dev = &pdev->dev;
+ platform_set_drvdata(pdev, pem_pmu);
+
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ pem_pmu->base = base;
+
+ pem_pmu->pmu = (struct pmu) {
+ .module = THIS_MODULE,
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
+ .task_ctx_nr = perf_invalid_context,
+ .attr_groups = pem_perf_attr_groups,
+ .event_init = pem_perf_event_init,
+ .add = pem_perf_event_add,
+ .del = pem_perf_event_del,
+ .start = pem_perf_event_start,
+ .stop = pem_perf_event_stop,
+ .read = pem_perf_event_update,
+ };
+
+ /* Choose this cpu to collect perf data */
+ pem_pmu->cpu = raw_smp_processor_id();
+
+ name = devm_kasprintf(pem_pmu->dev, GFP_KERNEL, "mrvl_pcie_rc_pmu_%llx",
+ res->start);
+ if (!name)
+ return -ENOMEM;
+
+ cpuhp_state_add_instance_nocalls
+ (CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE,
+ &pem_pmu->node);
+
+ ret = perf_pmu_register(&pem_pmu->pmu, name, -1);
+ if (ret)
+ goto error;
+
+ return 0;
+error:
+ cpuhp_state_remove_instance_nocalls
+ (CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE,
+ &pem_pmu->node);
+ return ret;
+}
+
+static int pem_perf_remove(struct platform_device *pdev)
+{
+ struct pem_pmu *pem_pmu = platform_get_drvdata(pdev);
+
+ cpuhp_state_remove_instance_nocalls
+ (CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE,
+ &pem_pmu->node);
+
+ perf_pmu_unregister(&pem_pmu->pmu);
+ return 0;
+}
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id pem_pmu_acpi_match[] = {
+ {"MRVL000E", 0},
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, pem_pmu_acpi_match);
+#endif
+
+static struct platform_driver pem_pmu_driver = {
+ .driver = {
+ .name = "pem-pmu",
+ .acpi_match_table = ACPI_PTR(pem_pmu_acpi_match),
+ .suppress_bind_attrs = true,
+ },
+ .probe = pem_perf_probe,
+ .remove = pem_perf_remove,
+};
+
+static int __init pem_pmu_init(void)
+{
+ int ret;
+
+ ret = cpuhp_setup_state_multi(CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE,
+ "perf/marvell/pem:online", NULL,
+ pem_pmu_offline_cpu);
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&pem_pmu_driver);
+ if (ret)
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE);
+ return ret;
+}
+
+static void __exit pem_pmu_exit(void)
+{
+ platform_driver_unregister(&pem_pmu_driver);
+ cpuhp_remove_multi_state(CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE);
+}
+
+module_init(pem_pmu_init);
+module_exit(pem_pmu_exit);
+
+MODULE_DESCRIPTION("Marvell PEM Perf driver");
+MODULE_AUTHOR("Linu Cherian <lcherian@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h
index 624d4a38c358..9bf34f66e5f5 100644
--- a/include/linux/cpuhotplug.h
+++ b/include/linux/cpuhotplug.h
@@ -238,6 +238,7 @@ enum cpuhp_state {
CPUHP_AP_PERF_ARM_APM_XGENE_ONLINE,
CPUHP_AP_PERF_ARM_CAVIUM_TX2_UNCORE_ONLINE,
CPUHP_AP_PERF_ARM_MARVELL_CN10K_DDR_ONLINE,
+ CPUHP_AP_PERF_ARM_MARVELL_PEM_ONLINE,
CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE,
CPUHP_AP_PERF_POWERPC_CORE_IMC_ONLINE,
CPUHP_AP_PERF_POWERPC_THREAD_IMC_ONLINE,
--
2.25.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Siddharth Vadapalli @ 2024-04-03 6:48 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Siddharth Vadapalli, lee, robh, krzk+dt, conor+dt, devicetree,
linux-kernel, linux-arm-kernel, srk
In-Reply-To: <083e50de-1c99-4a58-8b55-4dec26d97c1b@kernel.org>
On Wed, Apr 03, 2024 at 08:40:19AM +0200, Krzysztof Kozlowski wrote:
> On 03/04/2024 08:32, Siddharth Vadapalli wrote:
> > On Wed, Apr 03, 2024 at 08:27:06AM +0200, Krzysztof Kozlowski wrote:
> >> On 03/04/2024 07:35, Siddharth Vadapalli wrote:
> >>> On Tue, Apr 02, 2024 at 08:06:27PM +0200, Krzysztof Kozlowski wrote:
> >>>> On 02/04/2024 14:30, Siddharth Vadapalli wrote:
> >>>>> On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
> >>>>>> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
> >>>>>>> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
> >>>>>>> contain the MAC Address programmed in the eFuse. Add compatible for
> >>>>>>> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
> >>>>>>> registers within the System Controller device-tree node. The default MAC
> >>>>>>> Address for the interface corresponding to the first MAC port will be set
> >>>>>>> to the value programmed in the eFuse.
> >>>>>>>
> >>>>>>> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
> >>>>>>> ---
> >>>>>>>
> >>>>>>> This patch is based on linux-next tagged next-20240402.
> >>>>>>
> >>>>>> Where is the DTS using it?
> >>>>>
> >>>>> The current implementation in the device-tree for older TI K3 SoCs is as
> >>>>> follows:
> >>>>>
> >>>>> cpsw_port1: port@1 {
> >>>>> reg = <1>;
> >>>>> ti,mac-only;
> >>>>> label = "port1";
> >>>>> phys = <&phy_gmii_sel 1>;
> >>>>> mac-address = [00 00 00 00 00 00];
> >>>>> ti,syscon-efuse = <&wkup_conf 0x200>;
> >>>>> };
> >>>>>
> >>>>> The "ti,syscon-efuse" property passes the reference to the System
> >>>>> Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
> >>>>> within the CTRL_MMR space.
> >>>>
> >>>> Please reference upstream DTS or lore link to patch under review.
> >>>
> >>> An example of the existing implementation in the device-tree for AM64x
> >>> is:
> >>> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L697
> >>> It uses:
> >>> ti,syscon-efuse = <&main_conf 0x200>;
> >>>
> >>> and "main_conf" node is defined at:
> >>> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L40
> >>
> >> It is quite different than your bindings, so your bindings are incorrect.
> >
> > Sorry I didn't understand what you mean. The references I have provided
> > are for existing DTS where "main_conf"/"wkup_conf" (System Controller
> > nodes) have the compatible "syscon", unlike in AM62p at:
> > https://github.com/torvalds/linux/blob/20f8173afaac90dd9dca11be4aa602a47776077f/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi#L8
> > which has the "simple-bus" compatible for the "wkup_conf" node.
> >
> > Also, shouldn't the device-tree bindings patches be posted first and get
> > merged before I post the device-tree patches that utilize the
> > compatible/properties that have been added in the bindings? That is the
> > reason why I had shared the "DIFF" for the DTS changes that I will be
> > posting once this patch for the new compatible is accepted.
> >
>
> That's not the process. I will be NAKing bindings which do not have any
> users, because I do not trust you test them.
>
> The process is almost always:
> 1. Send bindings,
> 2. Send driver changes (if applicable) in the same patchset.
> 3. Send DTS, usually in separate patches and provide lore link to the
> bindings in the changelog or cover letter.
Thank you for clarifying. I will post the DTS patches corresponding to
this patch and reference this patch in the DTS patch series.
Regards,
Siddharth.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v2 01/18] PCI: endpoint: Introduce pci_epc_function_is_valid()
From: Manivannan Sadhasivam @ 2024-04-03 6:46 UTC (permalink / raw)
To: Damien Le Moal
Cc: Lorenzo Pieralisi, Kishon Vijay Abraham I, Shawn Lin,
Krzysztof Wilczyński, Bjorn Helgaas, Heiko Stuebner,
linux-pci, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
devicetree, linux-rockchip, linux-arm-kernel, Rick Wertenbroek,
Wilfred Mallawa, Niklas Cassel
In-Reply-To: <20240330041928.1555578-2-dlemoal@kernel.org>
On Sat, Mar 30, 2024 at 01:19:11PM +0900, Damien Le Moal wrote:
> Introduce the epc core helper function pci_epc_function_is_valid() to
> verify that an epc pointer, a physical function number and a virtual
> function number are all valid. This avoids repeating the code pattern:
>
> if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> return err;
>
> if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> return err;
>
> in many functions of the endpoint controller core code.
>
> Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
One nit below. With that fixed,
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> ---
> drivers/pci/endpoint/pci-epc-core.c | 79 +++++++++++------------------
> 1 file changed, 31 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
> index da3fc0795b0b..754afd115bbd 100644
> --- a/drivers/pci/endpoint/pci-epc-core.c
> +++ b/drivers/pci/endpoint/pci-epc-core.c
> @@ -126,6 +126,18 @@ enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
> }
> EXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar);
>
> +static inline bool pci_epc_function_is_valid(struct pci_epc *epc,
> + u8 func_no, u8 vfunc_no)
No need to add 'inline' keyword to function definitions in a .c file. Compiler
will handle that.
- Mani
> +{
> + if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> + return false;
> +
> + if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + return false;
> +
> + return true;
> +}
> +
> /**
> * pci_epc_get_features() - get the features supported by EPC
> * @epc: the features supported by *this* EPC device will be returned
> @@ -143,10 +155,7 @@ const struct pci_epc_features *pci_epc_get_features(struct pci_epc *epc,
> {
> const struct pci_epc_features *epc_features;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return NULL;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return NULL;
>
> if (!epc->ops->get_features)
> @@ -216,10 +225,7 @@ int pci_epc_raise_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> {
> int ret;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return -EINVAL;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> if (!epc->ops->raise_irq)
> @@ -260,10 +266,7 @@ int pci_epc_map_msi_irq(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> {
> int ret;
>
> - if (IS_ERR_OR_NULL(epc))
> - return -EINVAL;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> if (!epc->ops->map_msi_irq)
> @@ -291,10 +294,7 @@ int pci_epc_get_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
> {
> int interrupt;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return 0;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return 0;
>
> if (!epc->ops->get_msi)
> @@ -327,11 +327,10 @@ int pci_epc_set_msi(struct pci_epc *epc, u8 func_no, u8 vfunc_no, u8 interrupts)
> int ret;
> u8 encode_int;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
> - interrupts < 1 || interrupts > 32)
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (interrupts < 1 || interrupts > 32)
> return -EINVAL;
>
> if (!epc->ops->set_msi)
> @@ -359,10 +358,7 @@ int pci_epc_get_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no)
> {
> int interrupt;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return 0;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return 0;
>
> if (!epc->ops->get_msix)
> @@ -395,11 +391,10 @@ int pci_epc_set_msix(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> {
> int ret;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
> - interrupts < 1 || interrupts > 2048)
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (interrupts < 1 || interrupts > 2048)
> return -EINVAL;
>
> if (!epc->ops->set_msix)
> @@ -426,10 +421,7 @@ EXPORT_SYMBOL_GPL(pci_epc_set_msix);
> void pci_epc_unmap_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> phys_addr_t phys_addr)
> {
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return;
>
> if (!epc->ops->unmap_addr)
> @@ -457,10 +449,7 @@ int pci_epc_map_addr(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> {
> int ret;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return -EINVAL;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> if (!epc->ops->map_addr)
> @@ -487,12 +476,11 @@ EXPORT_SYMBOL_GPL(pci_epc_map_addr);
> void pci_epc_clear_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> struct pci_epf_bar *epf_bar)
> {
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
> - (epf_bar->barno == BAR_5 &&
> - epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return;
>
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (epf_bar->barno == BAR_5 &&
> + epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
> return;
>
> if (!epc->ops->clear_bar)
> @@ -519,18 +507,16 @@ int pci_epc_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> int ret;
> int flags = epf_bar->flags;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions ||
> - (epf_bar->barno == BAR_5 &&
> - flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> + return -EINVAL;
> +
> + if ((epf_bar->barno == BAR_5 && flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ||
> (flags & PCI_BASE_ADDRESS_SPACE_IO &&
> flags & PCI_BASE_ADDRESS_IO_MASK) ||
> (upper_32_bits(epf_bar->size) &&
> !(flags & PCI_BASE_ADDRESS_MEM_TYPE_64)))
> return -EINVAL;
>
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> - return -EINVAL;
> -
> if (!epc->ops->set_bar)
> return 0;
>
> @@ -559,10 +545,7 @@ int pci_epc_write_header(struct pci_epc *epc, u8 func_no, u8 vfunc_no,
> {
> int ret;
>
> - if (IS_ERR_OR_NULL(epc) || func_no >= epc->max_functions)
> - return -EINVAL;
> -
> - if (vfunc_no > 0 && (!epc->max_vfs || vfunc_no > epc->max_vfs[func_no]))
> + if (!pci_epc_function_is_valid(epc, func_no, vfunc_no))
> return -EINVAL;
>
> /* Only Virtual Function #1 has deviceID */
> --
> 2.44.0
>
--
மணிவண்ணன் சதாசிவம்
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [RFC][PATCH 0/2] Amlogic T7 (A113D2) Clock Driver
From: Xianwei Zhao @ 2024-04-03 6:44 UTC (permalink / raw)
To: Lucas Tanure, Yu Tu, Neil Armstrong, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Stephen Boyd, Michael Turquette
Cc: linux-arm-kernel, linux-amlogic, devicetree, linux-kernel,
linux-clk
In-Reply-To: <20240318114346.112935-1-tanure@linux.com>
Hi Lucas,
As we are preparing the T7 clock patchset, we would like to your
purpose and plan of this RFC patches. Are you going to submit these
patches at last?
On 2024/3/18 19:43, Lucas Tanure wrote:
> [ EXTERNAL EMAIL ]
>
> I am trying to port the T7 clock driver from Khadas 5.4 kernel for Vim4
> to mainline, but I am encountering some issues in the path.
>
> The kernel panics at clk_mux_val_to_index, but I believe that all the
> needed clocks are registered.
>
> If anyone from Amlogic or the community could help me understand what
> my driver is missing, that would be great.
> I will continue to try to figure out, but it has been some weeks
> without progress =/.
>
> Lucas Tanure (2):
> clk: meson: T7: add support for Amlogic T7 SoC PLL clock driver
> arm64: dts: amlogic: t7: SDCard, Ethernet and Clocking
>
> .../amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 66 +
> arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 189 +
> drivers/clk/meson/Kconfig | 25 +
> drivers/clk/meson/Makefile | 2 +
> drivers/clk/meson/t7-peripherals.c | 6368 +++++++++++++++++
> drivers/clk/meson/t7-peripherals.h | 131 +
> drivers/clk/meson/t7-pll.c | 1543 ++++
> drivers/clk/meson/t7-pll.h | 83 +
> .../clock/amlogic,t7-peripherals-clkc.h | 410 ++
> .../dt-bindings/clock/amlogic,t7-pll-clkc.h | 69 +
> 10 files changed, 8886 insertions(+)
> create mode 100644 drivers/clk/meson/t7-peripherals.c
> create mode 100644 drivers/clk/meson/t7-peripherals.h
> create mode 100644 drivers/clk/meson/t7-pll.c
> create mode 100644 drivers/clk/meson/t7-pll.h
> create mode 100644 include/dt-bindings/clock/amlogic,t7-peripherals-clkc.h
> create mode 100644 include/dt-bindings/clock/amlogic,t7-pll-clkc.h
>
> Starting kernel ...
>
> uboot time: 14277917 us
> boot 64bit kernel
> [ 0.000000] Booting Linux on physical CPU 0x0000000000 [0x410fd092]
> [ 0.000000] Linux version 6.8.0-09793-gda876e5b54b3-dirty (tanureal@ryzen) (aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.3.1 20210621, GNU ld (GNU Toolchain for the A-pr4
> [ 0.000000] KASLR disabled due to lack of seed
> [ 0.000000] Machine model: Khadas vim4
> [ 0.000000] efi: UEFI not found.
> [ 0.000000] OF: reserved mem: 0x0000000005000000..0x00000000052fffff (3072 KiB) nomap non-reusable secmon@5000000
> [ 0.000000] OF: reserved mem: 0x0000000005300000..0x00000000072fffff (32768 KiB) nomap non-reusable secmon@5300000
> [ 0.000000] NUMA: No NUMA configuration found
> [ 0.000000] NUMA: Faking a node at [mem 0x0000000000000000-0x00000000df7fffff]
> [ 0.000000] NUMA: NODE_DATA [mem 0xdf10c9c0-0xdf10efff]
> [ 0.000000] Zone ranges:
> [ 0.000000] DMA [mem 0x0000000000000000-0x00000000df7fffff]
> [ 0.000000] DMA32 empty
> [ 0.000000] Normal empty
> [ 0.000000] Movable zone start for each node
> [ 0.000000] Early memory node ranges
> [ 0.000000] node 0: [mem 0x0000000000000000-0x0000000004ffffff]
> [ 0.000000] node 0: [mem 0x0000000005000000-0x00000000072fffff]
> [ 0.000000] node 0: [mem 0x0000000007300000-0x00000000df7fffff]
> [ 0.000000] Initmem setup node 0 [mem 0x0000000000000000-0x00000000df7fffff]
> [ 0.000000] On node 0, zone DMA: 2048 pages in unavailable ranges
> [ 0.000000] cma: Reserved 32 MiB at 0x00000000d9800000 on node -1
> [ 0.000000] psci: probing for conduit method from DT.
> [ 0.000000] psci: PSCIv1.0 detected in firmware.
> [ 0.000000] psci: Using standard PSCI v0.2 function IDs
> [ 0.000000] psci: Trusted OS migration not required
> [ 0.000000] psci: SMC Calling Convention v1.1
> [ 0.000000] percpu: Embedded 24 pages/cpu s58152 r8192 d31960 u98304
> [ 0.000000] Detected VIPT I-cache on CPU0
> [ 0.000000] CPU features: detected: Spectre-v2
> [ 0.000000] CPU features: detected: Spectre-v4
> [ 0.000000] CPU features: detected: Spectre-BHB
> [ 0.000000] CPU features: detected: ARM erratum 858921
> [ 0.000000] alternatives: applying boot alternatives
> [ 0.000000] Kernel command line: root=UUID=a91e7bfe-4263-4e53-867d-7824e7c6a992 rw rootfstype=ext4 console=ttyS0,921600 no_console_suspend earlycon=ttyS0,0xfe078000 khadas_board=VIM4 androidboot.selinux=permissive androidboot.0
> [ 0.000000] Unknown kernel command line parameters "khadas_board=VIM4", will be passed to user space.
> [ 0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear)
> [ 0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
> [ 0.000000] Fallback order for Node 0: 0
> [ 0.000000] Built 1 zonelists, mobility grouping on. Total pages: 901152
> [ 0.000000] Policy zone: DMA
> [ 0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
> [ 0.000000] software IO TLB: SWIOTLB bounce buffer size adjusted to 3MB
> [ 0.000000] software IO TLB: area num 8.
> [ 0.000000] software IO TLB: SWIOTLB bounce buffer size roundup to 4MB
> [ 0.000000] software IO TLB: mapped [mem 0x00000000d8e00000-0x00000000d9200000] (4MB)
> [ 0.000000] Memory: 3445944K/3661824K available (16896K kernel code, 4426K rwdata, 9184K rodata, 9728K init, 611K bss, 183112K reserved, 32768K cma-reserved)
> [ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=8, Nodes=1
> [ 0.000000] rcu: Preemptible hierarchical RCU implementation.
> [ 0.000000] rcu: RCU restricting CPUs from NR_CPUS=256 to nr_cpu_ids=8.
> [ 0.000000] Trampoline variant of Tasks RCU enabled.
> [ 0.000000] Tracing variant of Tasks RCU enabled.
> [ 0.000000] rcu: RCU calculated value of scheduler-enlistment delay is 25 jiffies.
> [ 0.000000] rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=8
> [ 0.000000] RCU Tasks: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1.
> [ 0.000000] RCU Tasks Trace: Setting shift to 3 and lim to 1 rcu_task_cb_adjust=1.
> [ 0.000000] NR_IRQS: 64, nr_irqs: 64, preallocated irqs: 0
> [ 0.000000] GIC: GICv2 detected, but range too small and irqchip.gicv2_force_probe not set
> [ 0.000000] Root IRQ handler: gic_handle_irq
> [ 0.000000] rcu: srcu_init: Setting srcu_struct sizes based on contention.
> [ 0.000000] arch_timer: Enabling local workaround for ARM erratum 858921
> [ 0.000000] arch_timer: CPU0: Trapping CNTVCT access
> [ 0.000000] arch_timer: cp15 timer(s) running at 24.00MHz (phys).
> [ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x588fe9dc0, max_idle_ns: 440795202592 ns
> [ 0.000000] sched_clock: 56 bits at 24MHz, resolution 41ns, wraps every 4398046511097ns
> [ 0.000210] Console: colour dummy device 80x25
> [ 0.000253] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=96000)
> [ 0.000261] pid_max: default: 32768 minimum: 301
> [ 0.000300] LSM: initializing lsm=capability
> [ 0.000358] Mount-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
> [ 0.000371] Mountpoint-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
> [ 0.000920] cacheinfo: Unable to detect cache hierarchy for CPU 0
> [ 0.001389] rcu: Hierarchical SRCU implementation.
> [ 0.001391] rcu: Max phase no-delay instances is 1000.
> [ 0.001834] EFI services will not be available.
> [ 0.001999] smp: Bringing up secondary CPUs ...
> [ 0.002408] CPU features: detected: ARM erratum 845719
> [ 0.002426] Detected VIPT I-cache on CPU1
> [ 0.002516] CPU1: Booted secondary processor 0x0000000100 [0x410fd034]
> [ 0.003007] Detected VIPT I-cache on CPU2
> [ 0.003054] CPU2: Booted secondary processor 0x0000000101 [0x410fd034]
> [ 0.003497] Detected VIPT I-cache on CPU3
> [ 0.003546] CPU3: Booted secondary processor 0x0000000102 [0x410fd034]
> [ 0.003988] Detected VIPT I-cache on CPU4
> [ 0.004038] CPU4: Booted secondary processor 0x0000000103 [0x410fd034]
> [ 0.004472] Detected VIPT I-cache on CPU5
> [ 0.004509] arch_timer: Enabling local workaround for ARM erratum 858921
> [ 0.004519] arch_timer: CPU5: Trapping CNTVCT access
> [ 0.004527] CPU5: Booted secondary processor 0x0000000001 [0x410fd092]
> [ 0.004915] Detected VIPT I-cache on CPU6
> [ 0.004940] arch_timer: Enabling local workaround for ARM erratum 858921
> [ 0.004946] arch_timer: CPU6: Trapping CNTVCT access
> [ 0.004951] CPU6: Booted secondary processor 0x0000000002 [0x410fd092]
> [ 0.005333] Detected VIPT I-cache on CPU7
> [ 0.005358] arch_timer: Enabling local workaround for ARM erratum 858921
> [ 0.005364] arch_timer: CPU7: Trapping CNTVCT access
> [ 0.005369] CPU7: Booted secondary processor 0x0000000003 [0x410fd092]
> [ 0.005414] smp: Brought up 1 node, 8 CPUs
> [ 0.005419] SMP: Total of 8 processors activated.
> [ 0.005421] CPU: All CPU(s) started at EL2
> [ 0.005434] CPU features: detected: 32-bit EL0 Support
> [ 0.005437] CPU features: detected: 32-bit EL1 Support
> [ 0.005440] CPU features: detected: CRC32 instructions
> [ 0.005485] alternatives: applying system-wide alternatives
> [ 0.006730] devtmpfs: initialized
> [ 0.008534] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 7645041785100000 ns
> [ 0.008545] futex hash table entries: 2048 (order: 5, 131072 bytes, linear)
> [ 0.008989] pinctrl core: initialized pinctrl subsystem
> [ 0.009581] DMI not present or invalid.
> [ 0.011290] NET: Registered PF_NETLINK/PF_ROUTE protocol family
> [ 0.011944] DMA: preallocated 512 KiB GFP_KERNEL pool for atomic allocations
> [ 0.012293] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
> [ 0.012711] DMA: preallocated 512 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
> [ 0.012832] audit: initializing netlink subsys (disabled)
> [ 0.013075] audit: type=2000 audit(0.012:1): state=initialized audit_enabled=0 res=1
> [ 0.013508] thermal_sys: Registered thermal governor 'step_wise'
> [ 0.013512] thermal_sys: Registered thermal governor 'power_allocator'
> [ 0.013557] cpuidle: using governor menu
> [ 0.013675] hw-breakpoint: found 6 breakpoint and 4 watchpoint registers.
> [ 0.013784] ASID allocator initialised with 65536 entries
> [ 0.014630] Serial: AMBA PL011 UART driver
> [ 0.017553] Modules: 22496 pages in range for non-PLT usage
> [ 0.017556] Modules: 514016 pages in range for PLT usage
> [ 0.017980] HugeTLB: registered 1.00 GiB page size, pre-allocated 0 pages
> [ 0.017984] HugeTLB: 0 KiB vmemmap can be freed for a 1.00 GiB page
> [ 0.017988] HugeTLB: registered 32.0 MiB page size, pre-allocated 0 pages
> [ 0.017990] HugeTLB: 0 KiB vmemmap can be freed for a 32.0 MiB page
> [ 0.017993] HugeTLB: registered 2.00 MiB page size, pre-allocated 0 pages
> [ 0.017995] HugeTLB: 0 KiB vmemmap can be freed for a 2.00 MiB page
> [ 0.017997] HugeTLB: registered 64.0 KiB page size, pre-allocated 0 pages
> [ 0.018000] HugeTLB: 0 KiB vmemmap can be freed for a 64.0 KiB page
> [ 0.018247] Demotion targets for Node 0: null
> [ 0.018884] ACPI: Interpreter disabled.
> [ 0.019584] iommu: Default domain type: Translated
> [ 0.019587] iommu: DMA domain TLB invalidation policy: strict mode
> [ 0.019979] SCSI subsystem initialized
> [ 0.020174] usbcore: registered new interface driver usbfs
> [ 0.020187] usbcore: registered new interface driver hub
> [ 0.020200] usbcore: registered new device driver usb
> [ 0.020434] pps_core: LinuxPPS API ver. 1 registered
> [ 0.020437] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
> [ 0.020443] PTP clock support registered
> [ 0.020487] EDAC MC: Ver: 3.0.0
> [ 0.020717] scmi_core: SCMI protocol bus registered
> [ 0.021039] FPGA manager framework
> [ 0.021076] Advanced Linux Sound Architecture Driver Initialized.
> [ 0.021612] vgaarb: loaded
> [ 0.021857] clocksource: Switched to clocksource arch_sys_counter
> [ 0.021967] VFS: Disk quotas dquot_6.6.0
> [ 0.021984] VFS: Dquot-cache hash table entries: 512 (order 0, 4096 bytes)
> [ 0.022062] pnp: PnP ACPI: disabled
> [ 0.026651] NET: Registered PF_INET protocol family
> [ 0.026781] IP idents hash table entries: 65536 (order: 7, 524288 bytes, linear)
> [ 0.028598] tcp_listen_portaddr_hash hash table entries: 2048 (order: 3, 32768 bytes, linear)
> [ 0.028615] Table-perturb hash table entries: 65536 (order: 6, 262144 bytes, linear)
> [ 0.028622] TCP established hash table entries: 32768 (order: 6, 262144 bytes, linear)
> [ 0.028750] TCP bind hash table entries: 32768 (order: 8, 1048576 bytes, linear)
> [ 0.029019] TCP: Hash tables configured (established 32768 bind 32768)
> [ 0.029096] UDP hash table entries: 2048 (order: 4, 65536 bytes, linear)
> [ 0.029124] UDP-Lite hash table entries: 2048 (order: 4, 65536 bytes, linear)
> [ 0.029225] NET: Registered PF_UNIX/PF_LOCAL protocol family
> [ 0.029506] RPC: Registered named UNIX socket transport module.
> [ 0.029510] RPC: Registered udp transport module.
> [ 0.029512] RPC: Registered tcp transport module.
> [ 0.029513] RPC: Registered tcp-with-tls transport module.
> [ 0.029515] RPC: Registered tcp NFSv4.1 backchannel transport module.
> [ 0.029524] PCI: CLS 0 bytes, default 64
> [ 0.029649] Unpacking initramfs...
> [ 0.033933] kvm [1]: IPA Size Limit: 40 bits
> [ 0.034713] kvm [1]: Hyp mode initialized successfully
> [ 0.035476] Initialise system trusted keyrings
> [ 0.035582] workingset: timestamp_bits=42 max_order=20 bucket_order=0
> [ 0.035747] squashfs: version 4.0 (2009/01/31) Phillip Lougher
> [ 0.035906] NFS: Registering the id_resolver key type
> [ 0.035919] Key type id_resolver registered
> [ 0.035922] Key type id_legacy registered
> [ 0.035933] nfs4filelayout_init: NFSv4 File Layout Driver Registering...
> [ 0.035935] nfs4flexfilelayout_init: NFSv4 Flexfile Layout Driver Registering...
> [ 0.036031] 9p: Installing v9fs 9p2000 file system support
> [ 0.062587] Key type asymmetric registered
> [ 0.062596] Asymmetric key parser 'x509' registered
> [ 0.062657] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 245)
> [ 0.062661] io scheduler mq-deadline registered
> [ 0.062664] io scheduler kyber registered
> [ 0.062688] io scheduler bfq registered
> [ 0.063318] irq_meson_gpio: 157 to 12 gpio interrupt mux initialized
> [ 0.068061] EINJ: ACPI disabled.
> [ 0.072570] amlogic_t7_pll_probe
> [ 0.072855] amlogic_t7_pll_probe ret 0
> [ 0.072943] amlogic_a1_periphs_probe
> [ 0.078155] amlogic_a1_periphs_probe ret 0
> [ 0.084876] Serial: 8250/16550 driver, 4 ports, IRQ sharing enabled
> [ 0.086691] fe078000.serial: ttyS0 at MMIO 0xfe078000 (irq = 14, base_baud = 1500000) is a meson_uart
> [ 0.086710] printk: legacy console [ttyS0] enabled
> [ 0.229167] sysfs: cannot create duplicate filename '/class/tty/ttyS0'
> [ 0.229669] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 6.8.0-09793-gda876e5b54b3-dirty #15
> [ 0.230684] Hardware name: Khadas vim4 (DT)
> [ 0.231205] Call trace:
> [ 0.231509] dump_backtrace+0x94/0xec
> [ 0.231963] show_stack+0x18/0x24
> [ 0.232374] dump_stack_lvl+0x78/0x90
> [ 0.232829] dump_stack+0x18/0x24
> [ 0.233241] sysfs_warn_dup+0x64/0x80
> [ 0.233696] sysfs_do_create_link_sd+0xf0/0xf8
> [ 0.234248] sysfs_create_link+0x20/0x40
> [ 0.234736] device_add+0x27c/0x77c
> [ 0.235169] device_register+0x20/0x30
> [ 0.235635] tty_register_device_attr+0xfc/0x240
> [ 0.236209] tty_port_register_device_attr_serdev+0x8c/0xac
> [ 0.236902] serial_core_register_port+0x318/0x658
> [ 0.237498] serial_ctrl_register_port+0x10/0x1c
> [ 0.238072] uart_add_one_port+0x10/0x1c
> [ 0.238560] meson_uart_probe+0x2c0/0x3b4
> [ 0.239058] platform_probe+0x68/0xd8
> [ 0.239513] really_probe+0x148/0x2b4
> [ 0.239968] __driver_probe_device+0x78/0x12c
> [ 0.240510] driver_probe_device+0xdc/0x160
> [ 0.241030] __driver_attach+0x94/0x19c
> [ 0.241507] bus_for_each_dev+0x74/0xd4
> [ 0.241983] driver_attach+0x24/0x30
> [ 0.242428] bus_add_driver+0xe4/0x1e8
> [ 0.242893] driver_register+0x60/0x128
> [ 0.243370] __platform_driver_register+0x28/0x34
> [ 0.243955] meson_uart_platform_driver_init+0x1c/0x28
> [ 0.244594] do_one_initcall+0x6c/0x1b0
> [ 0.245071] kernel_init_freeable+0x1cc/0x294
> [ 0.245613] kernel_init+0x20/0x1dc
> [ 0.246046] ret_from_fork+0x10/0x20
> [ 0.246555] meson_uart fe078000.serial: Cannot register tty device on line 0
> [ 0.247729] msm_serial: driver initialized
> [ 0.248150] SuperH (H)SCI(F) driver initialized
> [ 0.248544] STM32 USART driver initialized
> [ 0.263927] loop: module loaded
> [ 0.264952] megasas: 07.727.03.00-rc1
> [ 0.271065] tun: Universal TUN/TAP device driver, 1.6
> [ 0.271824] thunder_xcv, ver 1.0
> [ 0.271878] thunder_bgx, ver 1.0
> [ 0.271956] nicpf, ver 1.0
> [ 0.273230] hns3: Hisilicon Ethernet Network Driver for Hip08 Family - version
> [ 0.273437] hns3: Copyright (c) 2017 Huawei Corporation.
> [ 0.274148] hclge is initializing
> [ 0.274541] e1000: Intel(R) PRO/1000 Network Driver
> [ 0.275116] e1000: Copyright (c) 1999-2006 Intel Corporation.
> [ 0.275860] e1000e: Intel(R) PRO/1000 Network Driver
> [ 0.276449] e1000e: Copyright(c) 1999 - 2015 Intel Corporation.
> [ 0.277209] igb: Intel(R) Gigabit Ethernet Network Driver
> [ 0.277867] igb: Copyright (c) 2007-2014 Intel Corporation.
> [ 0.278576] igbvf: Intel(R) Gigabit Virtual Function Network Driver
> [ 0.279330] igbvf: Copyright (c) 2009 - 2012 Intel Corporation.
> [ 0.280319] sky2: driver version 1.30
> [ 0.281597] VFIO - User Level meta-driver version: 0.3
> [ 0.283859] usbcore: registered new interface driver usb-storage
> [ 0.286328] i2c_dev: i2c /dev entries driver
> [ 0.292404] sdhci: Secure Digital Host Controller Interface driver
> [ 0.292481] sdhci: Copyright(c) Pierre Ossman
> [ 0.293577] Synopsys Designware Multimedia Card Interface Driver
> [ 0.294572] sdhci-pltfm: SDHCI platform and OF driver helper
> [ 0.296259] ledtrig-cpu: registered to indicate activity on CPUs
> [ 0.298966] meson-sm: secure-monitor enabled
> [ 0.299963] usbcore: registered new interface driver usbhid
> [ 0.299997] usbhid: USB HID core driver
> [ 0.306803] NET: Registered PF_PACKET protocol family
> [ 0.306919] 9pnet: Installing 9P2000 support
> [ 0.307331] Key type dns_resolver registered
> [ 0.318926] Timer migration: 1 hierarchy levels; 8 children per group; 1 crossnode level
> [ 0.319462] registered taskstats version 1
> [ 0.319968] Loading compiled-in X.509 certificates
> [ 0.362771] clk: Disabling unused clocks
> [ 0.363100] PM: genpd: Disabling unused power domains
> [ 0.363383] ALSA device list:
> [ 0.363580] No soundcards found.
> [ 0.368194] meson-gx-mmc fe08a000.sd: Got CD GPIO
> [ 0.368524] SError Interrupt on CPU6, code 0x00000000bf000002 -- SError
> [ 0.368531] CPU: 6 PID: 87 Comm: kworker/u32:3 Not tainted 6.8.0-09793-gda876e5b54b3-dirty #15
> [ 0.368537] Hardware name: Khadas vim4 (DT)
> [ 0.368540] Workqueue: async async_run_entry_fn
> [ 0.368552] pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
> [ 0.368556] pc : clk_mux_val_to_index+0x0/0xc0
> [ 0.368565] lr : clk_mux_get_parent+0x4c/0x84
> [ 0.368571] sp : ffff800082efba10
> [ 0.368572] x29: ffff800082efba10 x28: ffff8000823279c0 x27: ffff800082327000
> [ 0.368578] x26: ffff000004c361c0 x25: 0000000000000000 x24: 0000000000000002
> [ 0.368584] x23: ffff000003f1d300 x22: ffff000003f1d2a0 x21: ffff000004c37280
> [ 0.368589] x20: ffff000004c36ec0 x19: ffff000004bba800 x18: 0000000000000020
> [ 0.368594] x17: ffff000000022000 x16: 0000000000000003 x15: ffffffffffffffff
> [ 0.368599] x14: ffffffffffffffff x13: 0078756d2364732e x12: 3030306138306566
> [ 0.368604] x11: 7f7f7f7f7f7f7f7f x10: ffff7fff83438910 x9 : 0000000000000005
> [ 0.368609] x8 : 0101010101010101 x7 : 0000000000000000 x6 : 05114367045e5359
> [ 0.368613] x5 : 0000000000000006 x4 : 0000000000000000 x3 : 0000000000000000
> [ 0.368618] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff000004c36ec0
> [ 0.368624] Kernel panic - not syncing: Asynchronous SError Interrupt
> [ 0.368626] CPU: 6 PID: 87 Comm: kworker/u32:3 Not tainted 6.8.0-09793-gda876e5b54b3-dirty #15
> [ 0.368630] Hardware name: Khadas vim4 (DT)
> [ 0.368631] Workqueue: async async_run_entry_fn
> [ 0.368635] Call trace:
> [ 0.368637] dump_backtrace+0x94/0xec
> [ 0.368644] show_stack+0x18/0x24
> [ 0.368649] dump_stack_lvl+0x38/0x90
> [ 0.368656] dump_stack+0x18/0x24
> [ 0.368661] panic+0x388/0x3c8
> [ 0.368666] nmi_panic+0x48/0x94
> [ 0.368670] arm64_serror_panic+0x6c/0x78
> [ 0.368674] do_serror+0x3c/0x78
> [ 0.368677] el1h_64_error_handler+0x30/0x48
> [ 0.368681] el1h_64_error+0x64/0x68
> [ 0.368684] clk_mux_val_to_index+0x0/0xc0
> [ 0.368689] __clk_register+0x440/0x82c
> [ 0.368693] devm_clk_register+0x5c/0xbc
> [ 0.368697] meson_mmc_clk_init+0x11c/0x2a8
> [ 0.368702] meson_mmc_probe+0x18c/0x3c0
> [ 0.368705] platform_probe+0x68/0xd8
> [ 0.368711] really_probe+0x148/0x2b4
> [ 0.368714] __driver_probe_device+0x78/0x12c
> [ 0.368718] driver_probe_device+0xdc/0x160
> [ 0.368721] __device_attach_driver+0xb8/0x134
> [ 0.368724] bus_for_each_drv+0x84/0xe0
> [ 0.368727] __device_attach_async_helper+0xac/0xd0
> [ 0.368730] async_run_entry_fn+0x34/0xe0
> [ 0.368734] process_one_work+0x150/0x294
> [ 0.368740] worker_thread+0x304/0x408
> [ 0.368744] kthread+0x118/0x11c
> [ 0.368748] ret_from_fork+0x10/0x20
> [ 0.368753] SMP: stopping secondary CPUs
> [ 0.368760] Kernel Offset: disabled
> [ 0.368761] CPU features: 0x0,00000060,d0080000,0200421b
> [ 0.368765] Memory Limit: none
> [ 0.400328] ---[ end Kernel panic - not syncing: Asynchronous SError Interrupt ]---
>
>
> --
> 2.44.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH v1 1/1] drm/mediatek/dp: The register is written with the parsed DTS SSC value.
From: Krzysztof Kozlowski @ 2024-04-03 6:41 UTC (permalink / raw)
To: Liankun Yang, chunkuang.hu, p.zabel, chunfeng.yun, vkoul, kishon,
matthias.bgg, angelogioacchino.delregno, jitao.shi, mac.shen
Cc: dri-devel, linux-mediatek, linux-arm-kernel, linux-phy,
linux-kernel
In-Reply-To: <20240403040517.3279-1-liankun.yang@mediatek.com>
On 03/04/2024 06:05, Liankun Yang wrote:
> [Description]
> Severe screen flickering has been observed on the external display
> when the DP projection function is used with the market expansion dock.
>
> + if (!strcmp(mode_name, RG_XTP_GLB_TXPLL_SSC_DELTA_RBR)) {
> + regmap_update_bits(dp_phy->regs, ssc_reg_offset,
> + XTP_GLB_TXPLL_SSC_DELTA_RBR_DEFAULT, read_value);
> + } else if (!strcmp(mode_name, RG_XTP_GLB_TXPLL_SSC_DELTA_HBR)) {
> + read_value = read_value << 16 | 0x0000;
> + regmap_update_bits(dp_phy->regs, ssc_reg_offset,
> + XTP_GLB_TXPLL_SSC_DELTA_HBR_DEFAULT, read_value);
> + }
> +
> + return 0;
> +}
> +
> +static struct device_node *mtk_dp_get_ssc_node(struct phy *phy, struct mtk_dp_phy *dp_phy)
> +{
> + struct device_node *mode_node = NULL;
> +
> + mode_node = of_find_node_by_name(dp_phy->dev->of_node, SSC_SETTING);
?!?!
You have the node, why do you try to find it?
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Krzysztof Kozlowski @ 2024-04-03 6:40 UTC (permalink / raw)
To: Siddharth Vadapalli
Cc: lee, robh, krzk+dt, conor+dt, devicetree, linux-kernel,
linux-arm-kernel, srk
In-Reply-To: <af61424e-7006-49f5-b614-3caa3674685a@ti.com>
On 03/04/2024 08:32, Siddharth Vadapalli wrote:
> On Wed, Apr 03, 2024 at 08:27:06AM +0200, Krzysztof Kozlowski wrote:
>> On 03/04/2024 07:35, Siddharth Vadapalli wrote:
>>> On Tue, Apr 02, 2024 at 08:06:27PM +0200, Krzysztof Kozlowski wrote:
>>>> On 02/04/2024 14:30, Siddharth Vadapalli wrote:
>>>>> On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
>>>>>> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
>>>>>>> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
>>>>>>> contain the MAC Address programmed in the eFuse. Add compatible for
>>>>>>> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
>>>>>>> registers within the System Controller device-tree node. The default MAC
>>>>>>> Address for the interface corresponding to the first MAC port will be set
>>>>>>> to the value programmed in the eFuse.
>>>>>>>
>>>>>>> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
>>>>>>> ---
>>>>>>>
>>>>>>> This patch is based on linux-next tagged next-20240402.
>>>>>>
>>>>>> Where is the DTS using it?
>>>>>
>>>>> The current implementation in the device-tree for older TI K3 SoCs is as
>>>>> follows:
>>>>>
>>>>> cpsw_port1: port@1 {
>>>>> reg = <1>;
>>>>> ti,mac-only;
>>>>> label = "port1";
>>>>> phys = <&phy_gmii_sel 1>;
>>>>> mac-address = [00 00 00 00 00 00];
>>>>> ti,syscon-efuse = <&wkup_conf 0x200>;
>>>>> };
>>>>>
>>>>> The "ti,syscon-efuse" property passes the reference to the System
>>>>> Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
>>>>> within the CTRL_MMR space.
>>>>
>>>> Please reference upstream DTS or lore link to patch under review.
>>>
>>> An example of the existing implementation in the device-tree for AM64x
>>> is:
>>> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L697
>>> It uses:
>>> ti,syscon-efuse = <&main_conf 0x200>;
>>>
>>> and "main_conf" node is defined at:
>>> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L40
>>
>> It is quite different than your bindings, so your bindings are incorrect.
>
> Sorry I didn't understand what you mean. The references I have provided
> are for existing DTS where "main_conf"/"wkup_conf" (System Controller
> nodes) have the compatible "syscon", unlike in AM62p at:
> https://github.com/torvalds/linux/blob/20f8173afaac90dd9dca11be4aa602a47776077f/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi#L8
> which has the "simple-bus" compatible for the "wkup_conf" node.
>
> Also, shouldn't the device-tree bindings patches be posted first and get
> merged before I post the device-tree patches that utilize the
> compatible/properties that have been added in the bindings? That is the
> reason why I had shared the "DIFF" for the DTS changes that I will be
> posting once this patch for the new compatible is accepted.
>
That's not the process. I will be NAKing bindings which do not have any
users, because I do not trust you test them.
The process is almost always:
1. Send bindings,
2. Send driver changes (if applicable) in the same patchset.
3. Send DTS, usually in separate patches and provide lore link to the
bindings in the changelog or cover letter.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Siddharth Vadapalli @ 2024-04-03 6:32 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Siddharth Vadapalli, lee, robh, krzk+dt, conor+dt, devicetree,
linux-kernel, linux-arm-kernel, srk
In-Reply-To: <eb7a0d5c-c197-44b9-baea-e9b54792b447@kernel.org>
On Wed, Apr 03, 2024 at 08:27:06AM +0200, Krzysztof Kozlowski wrote:
> On 03/04/2024 07:35, Siddharth Vadapalli wrote:
> > On Tue, Apr 02, 2024 at 08:06:27PM +0200, Krzysztof Kozlowski wrote:
> >> On 02/04/2024 14:30, Siddharth Vadapalli wrote:
> >>> On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
> >>>> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
> >>>>> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
> >>>>> contain the MAC Address programmed in the eFuse. Add compatible for
> >>>>> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
> >>>>> registers within the System Controller device-tree node. The default MAC
> >>>>> Address for the interface corresponding to the first MAC port will be set
> >>>>> to the value programmed in the eFuse.
> >>>>>
> >>>>> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
> >>>>> ---
> >>>>>
> >>>>> This patch is based on linux-next tagged next-20240402.
> >>>>
> >>>> Where is the DTS using it?
> >>>
> >>> The current implementation in the device-tree for older TI K3 SoCs is as
> >>> follows:
> >>>
> >>> cpsw_port1: port@1 {
> >>> reg = <1>;
> >>> ti,mac-only;
> >>> label = "port1";
> >>> phys = <&phy_gmii_sel 1>;
> >>> mac-address = [00 00 00 00 00 00];
> >>> ti,syscon-efuse = <&wkup_conf 0x200>;
> >>> };
> >>>
> >>> The "ti,syscon-efuse" property passes the reference to the System
> >>> Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
> >>> within the CTRL_MMR space.
> >>
> >> Please reference upstream DTS or lore link to patch under review.
> >
> > An example of the existing implementation in the device-tree for AM64x
> > is:
> > https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L697
> > It uses:
> > ti,syscon-efuse = <&main_conf 0x200>;
> >
> > and "main_conf" node is defined at:
> > https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L40
>
> It is quite different than your bindings, so your bindings are incorrect.
Sorry I didn't understand what you mean. The references I have provided
are for existing DTS where "main_conf"/"wkup_conf" (System Controller
nodes) have the compatible "syscon", unlike in AM62p at:
https://github.com/torvalds/linux/blob/20f8173afaac90dd9dca11be4aa602a47776077f/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi#L8
which has the "simple-bus" compatible for the "wkup_conf" node.
Also, shouldn't the device-tree bindings patches be posted first and get
merged before I post the device-tree patches that utilize the
compatible/properties that have been added in the bindings? That is the
reason why I had shared the "DIFF" for the DTS changes that I will be
posting once this patch for the new compatible is accepted.
Regards,
Siddharth.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Krzysztof Kozlowski @ 2024-04-03 6:27 UTC (permalink / raw)
To: Siddharth Vadapalli
Cc: lee, robh, krzk+dt, conor+dt, devicetree, linux-kernel,
linux-arm-kernel, srk
In-Reply-To: <aabea385-16e0-4116-a12b-3ce1e06574e3@ti.com>
On 03/04/2024 07:35, Siddharth Vadapalli wrote:
> On Tue, Apr 02, 2024 at 08:06:27PM +0200, Krzysztof Kozlowski wrote:
>> On 02/04/2024 14:30, Siddharth Vadapalli wrote:
>>> On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
>>>> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
>>>>> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
>>>>> contain the MAC Address programmed in the eFuse. Add compatible for
>>>>> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
>>>>> registers within the System Controller device-tree node. The default MAC
>>>>> Address for the interface corresponding to the first MAC port will be set
>>>>> to the value programmed in the eFuse.
>>>>>
>>>>> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
>>>>> ---
>>>>>
>>>>> This patch is based on linux-next tagged next-20240402.
>>>>
>>>> Where is the DTS using it?
>>>
>>> The current implementation in the device-tree for older TI K3 SoCs is as
>>> follows:
>>>
>>> cpsw_port1: port@1 {
>>> reg = <1>;
>>> ti,mac-only;
>>> label = "port1";
>>> phys = <&phy_gmii_sel 1>;
>>> mac-address = [00 00 00 00 00 00];
>>> ti,syscon-efuse = <&wkup_conf 0x200>;
>>> };
>>>
>>> The "ti,syscon-efuse" property passes the reference to the System
>>> Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
>>> within the CTRL_MMR space.
>>
>> Please reference upstream DTS or lore link to patch under review.
>
> An example of the existing implementation in the device-tree for AM64x
> is:
> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L697
> It uses:
> ti,syscon-efuse = <&main_conf 0x200>;
>
> and "main_conf" node is defined at:
> https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L40
It is quite different than your bindings, so your bindings are incorrect.
Please fix them and send when your DTS is ready.
Best regards,
Krzysztof
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: About upstreaming ArmChina NPU driver
From: Oded Gabbay @ 2024-04-03 6:25 UTC (permalink / raw)
To: Dejia Shang
Cc: ogabbay@kernel.org, airlied@redhat.com, daniel@ffwll.ch,
linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <SH0PR01MB063461EBC046437C88A6AE84983BA@SH0PR01MB0634.CHNPR01.prod.partner.outlook.cn>
On Thu, Mar 28, 2024 at 10:01 AM Dejia Shang <Dejia.Shang@armchina.com> wrote:
>
> Dear Kernel Maintainers,
>
> I am a driver developer and would like to upstream the ArmChina Zhouyi NPU driver ("Zhouyi" is the brand) to accel subsystem.
>
> The driver is already open sourced (both UMD and KMD) and anyone can find the code from https://github.com/Arm-China/Compass_NPU_Driver.git.
>
> This driver is responsible for scheduling AI inference tasks to the NPU cores (V1/V2/V3). Specifically, a simplified end-to-end flow is:
>
> 1. A TFLite/ONNX model is transformed to an executable binary file in ELF format by the NN graph compiler (designed by ArmChina)
> 2. An application loads the executable binary file to UMD and provides the input data.
> 3. UMD parses the binary and sends ioctls to KMD (open device, do memory allocation/mmap/free, submit the job descriptor).
> 4. KMD dispatches the job to NPU h/w, handles interrupts and updates the execution status.
> 5. UMD polls the status of the pre-scheduled job.
> 6. The application gets the output results.
>
> So...for the upstreaming,
>
> Q1: do you think our NPU driver is suitable for accel? If the answer is yes, which tree & branch should the patches be based on?
Hi Dejia,
Yes, it definitely sounds as a good fit to the accel subsystem.
Please base your patches on "drm-misc-next" branch in drm-misc repo:
https://anongit.freedesktop.org/git/drm/drm-misc.git
>
> Q2: in thread https://lore.kernel.org/lkml/ec547d33-214f-4952-aa33-c271e9edad63@kernel.org/ showing a similar case, Oded mentioned that:
>
> "If we would have upstreamed a new driver, the expectation would have been that we would use some drm mechanisms.", and
> "the minimal requirement is to use GEM/BOs for memory management operations".
>
> I guess those requirements are also applicable for the Zhouyi NPU KMD? Currently, the memory management (MM) in KMD is based on dma-mapping APIs, which handles both reserved CMA region(s) and SMMU mapped buffers, and supports the dma-buf framework. Maybe I should replace the implementations with DRM APIs.
Yes, those requirements definitely apply here.
>
> Q3: if you have looked at the KMD code, do you think I should make any other major change before submitting the first patch series? Thank you!
I took a quick glance. In general, it seems to be ok, but I noticed
two things related to the integration with drm/accel:
1. You us a scheduler for the job submission, which provides the
ability to defer jobs. In that case, I suggest to check if you can use
drm_sched instead of your own implementation. No point in re-inventing
the wheel.
2. You provide several memory zones for allocation of memory. I would
suggest here to look at using ttm as the memory manager instead of
re-implementing your own.
And please remove the IMPORTANT NOTICE at the end of your emails. I
would have to refrain from answering to further emails if that notice
remains.
Thanks,
Oded
>
> Thanks for your time and look forward to your reply~ 😊
>
> Best Regards,
> Dejia
> IMPORTANT NOTICE: The contents of this email and any attachments may be privileged and confidential. If you are not the intended recipient, please delete the email immediately. It is strictly prohibited to disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. ©Arm Technology (China) Co., Ltd copyright and reserve all rights. 重要提示:本邮件(包括任何附件)可能含有专供明确的个人或目的使用的机密信息,并受法律保护。如果您并非该收件人,请立即删除此邮件。严禁通过任何渠道,以任何目的,向任何人披露、储存或复制邮件信息或者据此采取任何行动。感谢您的配合。 ©安谋科技(中国)有限公司 版权所有并保留一切权利。
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 2/7] arm64: mm: accelerate pagefault when VM_FAULT_BADACCESS
From: Kefeng Wang @ 2024-04-03 6:13 UTC (permalink / raw)
To: Suren Baghdasaryan
Cc: akpm, Russell King, Catalin Marinas, Will Deacon,
Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexander Gordeev,
Gerald Schaefer, Dave Hansen, Andy Lutomirski, Peter Zijlstra,
x86, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390
In-Reply-To: <CAJuCfpHkrwPp0X65BuYS2SKAkWPJDMNWYPDO+Jr4SmuxoCEsZg@mail.gmail.com>
On 2024/4/3 13:30, Suren Baghdasaryan wrote:
> On Tue, Apr 2, 2024 at 10:19 PM Suren Baghdasaryan <surenb@google.com> wrote:
>>
>> On Tue, Apr 2, 2024 at 12:53 AM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>>>
>>> The vm_flags of vma already checked under per-VMA lock, if it is a
>>> bad access, directly set fault to VM_FAULT_BADACCESS and handle error,
>>> no need to lock_mm_and_find_vma() and check vm_flags again, the latency
>>> time reduce 34% in lmbench 'lat_sig -P 1 prot lat_sig'.
>>
>> The change makes sense to me. Per-VMA lock is enough to keep
>> vma->vm_flags stable, so no need to retry with mmap_lock.
>>
>>>
>>> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
>>
>> Reviewed-by: Suren Baghdasaryan <surenb@google.com>
>>
>>> ---
>>> arch/arm64/mm/fault.c | 4 +++-
>>> 1 file changed, 3 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
>>> index 9bb9f395351a..405f9aa831bd 100644
>>> --- a/arch/arm64/mm/fault.c
>>> +++ b/arch/arm64/mm/fault.c
>>> @@ -572,7 +572,9 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr,
>>>
>>> if (!(vma->vm_flags & vm_flags)) {
>>> vma_end_read(vma);
>>> - goto lock_mmap;
>>> + fault = VM_FAULT_BADACCESS;
>>> + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
>>
>> nit: VMA_LOCK_SUCCESS accounting here seems correct to me but
>> unrelated to the main change. Either splitting into a separate patch
>> or mentioning this additional fixup in the changelog would be helpful.
>
> The above nit applies to all the patches after this one, so I won't
> comment on each one separately. If you decide to split or adjust the
> changelog please do that for each patch.
I will update the change log for each patch, thank for your review and
suggestion.
>
>>
>>> + goto done;
>>> }
>>> fault = handle_mm_fault(vma, addr, mm_flags | FAULT_FLAG_VMA_LOCK, regs);
>>> if (!(fault & (VM_FAULT_RETRY | VM_FAULT_COMPLETED)))
>>> --
>>> 2.27.0
>>>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] irqchip/gic-v3-its: Don't need VSYNC if VMAPP with {V, Alloc}=={0, x}
From: Marc Zyngier @ 2024-04-03 6:00 UTC (permalink / raw)
To: Tangnianyao; +Cc: tglx, linux-arm-kernel, linux-kernel, guoyang2, wangwudi
In-Reply-To: <cc7a6d40-7fdc-196e-56bc-fe8a15ea29bb@huawei.com>
On Wed, 03 Apr 2024 03:18:51 +0100,
Tangnianyao <tangnianyao@huawei.com> wrote:
>
>
>
> On 4/2/2024 21:43, Marc Zyngier wrote:
> > On Tue, 02 Apr 2024 14:32:40 +0100,
> > Tangnianyao <tangnianyao@huawei.com> wrote:
> >>
> >>
> >> Thank you for quick fix, it would be great to remove this VSYNC. ITS handling VSYNC unmap
> >> vpeid may waste some time, trigger exception and needed to be
> >> handled.
> > Do you actually see an exception being delivered from this?
> >
> > In any case, feel free to respin the patch after having tested this
> > diff, with the commit message fixed and a Fixes: tag attached to it.
>
> In our developing implemenation, ITS would report RAS when doing vsync
> and reaching an invalid vpe table entry. It is reasonable to report RAS, right?
If a RAS error is the only reporting method you have, then I suspect
you don't have much of a choice (the pseudocode indicates an IMPDEF
SError for VSYNC). Shame this wasn't caught earlier.
> It just reports, and kernel can still run normally regardless of
> this RAS message.
That really depends on the policy behind RAS errors.
Looking forward to your respinning of this patch.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 7/7] x86: mm: accelerate pagefault when badaccess
From: Suren Baghdasaryan @ 2024-04-03 5:59 UTC (permalink / raw)
To: Kefeng Wang
Cc: akpm, Russell King, Catalin Marinas, Will Deacon,
Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexander Gordeev,
Gerald Schaefer, Dave Hansen, Andy Lutomirski, Peter Zijlstra,
x86, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390
In-Reply-To: <20240402075142.196265-8-wangkefeng.wang@huawei.com>
On Tue, Apr 2, 2024 at 12:53 AM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>
> The vm_flags of vma already checked under per-VMA lock, if it is a
> bad access, directly handle error and return, there is no need to
> lock_mm_and_find_vma() and check vm_flags again.
>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Looks safe to me.
Using (mm != NULL) to indicate that we are holding mmap_lock is not
ideal but I guess that works.
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
> ---
> arch/x86/mm/fault.c | 23 ++++++++++++++---------
> 1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index a4cc20d0036d..67b18adc75dd 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -866,14 +866,17 @@ bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
>
> static void
> __bad_area(struct pt_regs *regs, unsigned long error_code,
> - unsigned long address, u32 pkey, int si_code)
> + unsigned long address, struct mm_struct *mm,
> + struct vm_area_struct *vma, u32 pkey, int si_code)
> {
> - struct mm_struct *mm = current->mm;
> /*
> * Something tried to access memory that isn't in our memory map..
> * Fix it, but check if it's kernel or user first..
> */
> - mmap_read_unlock(mm);
> + if (mm)
> + mmap_read_unlock(mm);
> + else
> + vma_end_read(vma);
>
> __bad_area_nosemaphore(regs, error_code, address, pkey, si_code);
> }
> @@ -897,7 +900,8 @@ static inline bool bad_area_access_from_pkeys(unsigned long error_code,
>
> static noinline void
> bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
> - unsigned long address, struct vm_area_struct *vma)
> + unsigned long address, struct mm_struct *mm,
> + struct vm_area_struct *vma)
> {
> /*
> * This OSPKE check is not strictly necessary at runtime.
> @@ -927,9 +931,9 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
> */
> u32 pkey = vma_pkey(vma);
>
> - __bad_area(regs, error_code, address, pkey, SEGV_PKUERR);
> + __bad_area(regs, error_code, address, mm, vma, pkey, SEGV_PKUERR);
> } else {
> - __bad_area(regs, error_code, address, 0, SEGV_ACCERR);
> + __bad_area(regs, error_code, address, mm, vma, 0, SEGV_ACCERR);
> }
> }
>
> @@ -1357,8 +1361,9 @@ void do_user_addr_fault(struct pt_regs *regs,
> goto lock_mmap;
>
> if (unlikely(access_error(error_code, vma))) {
> - vma_end_read(vma);
> - goto lock_mmap;
> + bad_area_access_error(regs, error_code, address, NULL, vma);
> + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
> + return;
> }
> fault = handle_mm_fault(vma, address, flags | FAULT_FLAG_VMA_LOCK, regs);
> if (!(fault & (VM_FAULT_RETRY | VM_FAULT_COMPLETED)))
> @@ -1394,7 +1399,7 @@ void do_user_addr_fault(struct pt_regs *regs,
> * we can handle it..
> */
> if (unlikely(access_error(error_code, vma))) {
> - bad_area_access_error(regs, error_code, address, vma);
> + bad_area_access_error(regs, error_code, address, mm, vma);
> return;
> }
>
> --
> 2.27.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] wifi: mt76: mt7603: add debugfs attr for disabling frames buffering
From: Rafał Miłecki @ 2024-04-03 4:40 UTC (permalink / raw)
To: Shengyu Qu, Felix Fietkau, Lorenzo Bianconi, Ryder Lee,
Shayne Chen, Sean Wang
Cc: Kalle Valo, Matthias Brugger, AngeloGioacchino Del Regno,
linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
openwrt-devel, Rafał Miłecki
In-Reply-To: <TY3P286MB261180E5A3A3A11351441DEC983E2@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM>
On 2.04.2024 18:54, Shengyu Qu wrote:
> Maybe we could disable frames buffering by default until it is fixed?
Please check commit description:
"If this solution yields a success we can make this feature disabled by default."
> Also, maybe we could do more tests on newer models such as mt7986/81 to
> make this patch benefit more models?
Can you point me to the mt7915 driver buffering code? I clearly missed that.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH v2] iommu/arm-smmu-v3: Free MSIs in case of ENOMEM
From: Aleksandr Aprelkov @ 2024-04-03 5:37 UTC (permalink / raw)
To: Will Deacon
Cc: Aleksandr Aprelkov, Robin Murphy, Joerg Roedel, Jason Gunthorpe,
Nicolin Chen, Michael Shavit, Lu Baolu, Marc Zyngier,
linux-arm-kernel, iommu, linux-kernel
If devm_add_action() returns ENOMEM, then MSIs allocated but
not freed on teardown.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 166bdbd23161 ("iommu/arm-smmu: Add support for MSI on SMMUv3")
Signed-off-by: Aleksandr Aprelkov <aaprelkov@usergate.com>
---
v2: Use appropriate function for registration failure as
Jonathan Cameron <Jonathan.Cameron@Huawei.com> suggested.
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 41f93c3ab160..8800af041e5f 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -3402,7 +3402,9 @@ static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
smmu->priq.q.irq = msi_get_virq(dev, PRIQ_MSI_INDEX);
/* Add callback to free MSIs on teardown */
- devm_add_action(dev, arm_smmu_free_msis, dev);
+ ret = devm_add_action_or_reset(dev, arm_smmu_free_msis, dev);
+ if (ret)
+ dev_warn(dev, "failed to add free MSIs callback - falling back to wired irqs\n");
}
static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH 5/7] riscv: mm: accelerate pagefault when badaccess
From: Suren Baghdasaryan @ 2024-04-03 5:37 UTC (permalink / raw)
To: Kefeng Wang
Cc: akpm, Russell King, Catalin Marinas, Will Deacon,
Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexander Gordeev,
Gerald Schaefer, Dave Hansen, Andy Lutomirski, Peter Zijlstra,
x86, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390
In-Reply-To: <20240402075142.196265-6-wangkefeng.wang@huawei.com>
On Tue, Apr 2, 2024 at 12:53 AM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>
> The vm_flags of vma already checked under per-VMA lock, if it is a
> bad access, directly handle error and return, there is no need to
> lock_mm_and_find_vma() and check vm_flags again.
>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
> ---
> arch/riscv/mm/fault.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c
> index 3ba1d4dde5dd..b3fcf7d67efb 100644
> --- a/arch/riscv/mm/fault.c
> +++ b/arch/riscv/mm/fault.c
> @@ -292,7 +292,10 @@ void handle_page_fault(struct pt_regs *regs)
>
> if (unlikely(access_error(cause, vma))) {
> vma_end_read(vma);
> - goto lock_mmap;
> + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
> + tsk->thread.bad_cause = SEGV_ACCERR;
> + bad_area_nosemaphore(regs, code, addr);
> + return;
> }
>
> fault = handle_mm_fault(vma, addr, flags | FAULT_FLAG_VMA_LOCK, regs);
> --
> 2.27.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH] dt-bindings: mfd: syscon: Add ti,am62p-cpsw-mac-efuse compatible
From: Siddharth Vadapalli @ 2024-04-03 5:35 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Siddharth Vadapalli, lee, robh, krzk+dt, conor+dt, devicetree,
linux-kernel, linux-arm-kernel, srk
In-Reply-To: <4b1380a8-0136-4395-ba42-9bcff2e1bdb0@kernel.org>
On Tue, Apr 02, 2024 at 08:06:27PM +0200, Krzysztof Kozlowski wrote:
> On 02/04/2024 14:30, Siddharth Vadapalli wrote:
> > On Tue, Apr 02, 2024 at 02:08:32PM +0200, Krzysztof Kozlowski wrote:
> >> On 02/04/2024 12:57, Siddharth Vadapalli wrote:
> >>> The CTRLMMR_MAC_IDx registers within the CTRL_MMR space of TI's AM62p SoC
> >>> contain the MAC Address programmed in the eFuse. Add compatible for
> >>> allowing the CPSW driver to obtain a regmap for the CTRLMMR_MAC_IDx
> >>> registers within the System Controller device-tree node. The default MAC
> >>> Address for the interface corresponding to the first MAC port will be set
> >>> to the value programmed in the eFuse.
> >>>
> >>> Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
> >>> ---
> >>>
> >>> This patch is based on linux-next tagged next-20240402.
> >>
> >> Where is the DTS using it?
> >
> > The current implementation in the device-tree for older TI K3 SoCs is as
> > follows:
> >
> > cpsw_port1: port@1 {
> > reg = <1>;
> > ti,mac-only;
> > label = "port1";
> > phys = <&phy_gmii_sel 1>;
> > mac-address = [00 00 00 00 00 00];
> > ti,syscon-efuse = <&wkup_conf 0x200>;
> > };
> >
> > The "ti,syscon-efuse" property passes the reference to the System
> > Controller node as well as the offset to the CTRLMMR_MAC_IDx registers
> > within the CTRL_MMR space.
>
> Please reference upstream DTS or lore link to patch under review.
An example of the existing implementation in the device-tree for AM64x
is:
https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L697
It uses:
ti,syscon-efuse = <&main_conf 0x200>;
and "main_conf" node is defined at:
https://github.com/torvalds/linux/blob/d4e8c8ad5d14ad51ed8813442d81c43019fd669d/arch/arm64/boot/dts/ti/k3-am64-main.dtsi#L40
Regards,
Siddharth.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 4/7] powerpc: mm: accelerate pagefault when badaccess
From: Suren Baghdasaryan @ 2024-04-03 5:34 UTC (permalink / raw)
To: Kefeng Wang
Cc: akpm, Russell King, Catalin Marinas, Will Deacon,
Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Paul Walmsley, Palmer Dabbelt, Albert Ou, Alexander Gordeev,
Gerald Schaefer, Dave Hansen, Andy Lutomirski, Peter Zijlstra,
x86, linux-arm-kernel, linuxppc-dev, linux-riscv, linux-s390
In-Reply-To: <20240402075142.196265-5-wangkefeng.wang@huawei.com>
On Tue, Apr 2, 2024 at 12:53 AM Kefeng Wang <wangkefeng.wang@huawei.com> wrote:
>
> The vm_flags of vma already checked under per-VMA lock, if it is a
> bad access, directly handle error and return, there is no need to
> lock_mm_and_find_vma() and check vm_flags again.
>
> Signed-off-by: Kefeng Wang <wangkefeng.wang@huawei.com>
Code-wise looks correct to me and almost identical to x86 change but
someone with more experience with this architecture should review.
> ---
> arch/powerpc/mm/fault.c | 33 ++++++++++++++++++++-------------
> 1 file changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 53335ae21a40..215690452495 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -71,23 +71,26 @@ static noinline int bad_area_nosemaphore(struct pt_regs *regs, unsigned long add
> return __bad_area_nosemaphore(regs, address, SEGV_MAPERR);
> }
>
> -static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code)
> +static int __bad_area(struct pt_regs *regs, unsigned long address, int si_code,
> + struct mm_struct *mm, struct vm_area_struct *vma)
> {
> - struct mm_struct *mm = current->mm;
>
> /*
> * Something tried to access memory that isn't in our memory map..
> * Fix it, but check if it's kernel or user first..
> */
> - mmap_read_unlock(mm);
> + if (mm)
> + mmap_read_unlock(mm);
> + else
> + vma_end_read(vma);
>
> return __bad_area_nosemaphore(regs, address, si_code);
> }
>
> static noinline int bad_access_pkey(struct pt_regs *regs, unsigned long address,
> + struct mm_struct *mm,
> struct vm_area_struct *vma)
> {
> - struct mm_struct *mm = current->mm;
> int pkey;
>
> /*
> @@ -109,7 +112,10 @@ static noinline int bad_access_pkey(struct pt_regs *regs, unsigned long address,
> */
> pkey = vma_pkey(vma);
>
> - mmap_read_unlock(mm);
> + if (mm)
> + mmap_read_unlock(mm);
> + else
> + vma_end_read(vma);
>
> /*
> * If we are in kernel mode, bail out with a SEGV, this will
> @@ -124,9 +130,10 @@ static noinline int bad_access_pkey(struct pt_regs *regs, unsigned long address,
> return 0;
> }
>
> -static noinline int bad_access(struct pt_regs *regs, unsigned long address)
> +static noinline int bad_access(struct pt_regs *regs, unsigned long address,
> + struct mm_struct *mm, struct vm_area_struct *vma)
> {
> - return __bad_area(regs, address, SEGV_ACCERR);
> + return __bad_area(regs, address, SEGV_ACCERR, mm, vma);
> }
>
> static int do_sigbus(struct pt_regs *regs, unsigned long address,
> @@ -479,13 +486,13 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
>
> if (unlikely(access_pkey_error(is_write, is_exec,
> (error_code & DSISR_KEYFAULT), vma))) {
> - vma_end_read(vma);
> - goto lock_mmap;
> + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
> + return bad_access_pkey(regs, address, NULL, vma);
> }
>
> if (unlikely(access_error(is_write, is_exec, vma))) {
> - vma_end_read(vma);
> - goto lock_mmap;
> + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
> + return bad_access(regs, address, NULL, vma);
> }
>
> fault = handle_mm_fault(vma, address, flags | FAULT_FLAG_VMA_LOCK, regs);
> @@ -521,10 +528,10 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address,
>
> if (unlikely(access_pkey_error(is_write, is_exec,
> (error_code & DSISR_KEYFAULT), vma)))
> - return bad_access_pkey(regs, address, vma);
> + return bad_access_pkey(regs, address, mm, vma);
>
> if (unlikely(access_error(is_write, is_exec, vma)))
> - return bad_access(regs, address);
> + return bad_access(regs, address, mm, vma);
>
> /*
> * If for any reason at all we couldn't handle the fault,
> --
> 2.27.0
>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox