* Re: [PATCH v2 1/3] dt-bindings: display: msm: qcm2290: Add Shikra MDSS
From: Krzysztof Kozlowski @ 2026-06-04 12:51 UTC (permalink / raw)
To: Nabige Aala, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Krishna Manikandan, Loic Poulain, Bjorn Andersson, Konrad Dybcio,
Will Deacon, Robin Murphy, Joerg Roedel (AMD)
Cc: linux-arm-msm, dri-devel, freedreno, devicetree, linux-kernel,
iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-1-b3c1b2b67edc@oss.qualcomm.com>
On 04/06/2026 14:30, Nabige Aala wrote:
>
> +select:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - qcom,qcm2290-mdss
> + required:
> + - compatible
Why do you need this select? None of the bindings have it, I think.
> +
> properties:
> compatible:
> - const: qcom,qcm2290-mdss
> + oneOf:
> + - const: qcom,qcm2290-mdss
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 1/3] dt-bindings: display: msm: qcm2290: Add Shikra MDSS
From: Dmitry Baryshkov @ 2026-06-04 12:51 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-1-b3c1b2b67edc@oss.qualcomm.com>
On Thu, Jun 04, 2026 at 06:00:47PM +0530, Nabige Aala wrote:
> Shikra SoC uses the same MDSS/DPU/DSI hardware as QCM2290 (DPU 6.5),
> sharing the same register layout, DSI controller and 14nm DSI PHY.
> Add qcom,shikra-mdss to the qcm2290-mdss binding compatible enum
> rather than introducing a separate binding file.
>
> Register qcom,shikra-dsi-ctrl in dsi-controller-main.yaml alongside
> qcom,qcm2290-dsi-ctrl, and update the qcm2290-mdss patternProperties
> to accept both SoC-specific DPU and DSI controller compatibles.
>
> Signed-off-by: Nabige Aala <nabige.aala@oss.qualcomm.com>
> ---
> .../bindings/display/msm/dsi-controller-main.yaml | 1 +
> .../bindings/display/msm/qcom,qcm2290-dpu.yaml | 7 ++--
> .../bindings/display/msm/qcom,qcm2290-mdss.yaml | 38 ++++++++++++++++++----
> 3 files changed, 37 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> index dbc0613e427e..a2f3e91104af 100644
> --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
> @@ -33,6 +33,7 @@ properties:
> - qcom,sdm660-dsi-ctrl
> - qcom,sdm670-dsi-ctrl
> - qcom,sdm845-dsi-ctrl
> + - qcom,shikra-dsi-ctrl
It is the same as QCM2290. Why didn't you follow the pattern and add it
using qcm2290 one as a fallback?
> - qcom,sm6115-dsi-ctrl
> - qcom,sm6125-dsi-ctrl
> - qcom,sm6150-dsi-ctrl
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> index be6cd8adb3b6..e166a73651df 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
> @@ -13,8 +13,11 @@ $ref: /schemas/display/msm/dpu-common.yaml#
>
> properties:
> compatible:
> - const: qcom,qcm2290-dpu
> -
> + oneOf:
> + - const: qcom,qcm2290-dpu
> + - items:
> + - const: qcom,shikra-dpu
> + - const: qcom,qcm2290-dpu
> reg:
> items:
> - description: Address offset and size for mdp register set
> diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> index bb09ecd1a5b4..7184b09a8774 100644
> --- a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> +++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
> @@ -4,21 +4,36 @@
> $id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml#
> $schema: http://devicetree.org/meta-schemas/core.yaml#
>
> -title: Qualcomm QCM220 Display MDSS
> +title: Qualcomm QCM2290 and Shikra Display MDSS
>
> maintainers:
> - Loic Poulain <loic.poulain@linaro.org>
> + - Nabige Aala <nabige.aala@oss.qualcomm.com>
Nope.
>
> description:
> Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
> sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
> - are mentioned for QCM2290 target.
> + are mentioned for QCM2290 and Shikra targets. Shikra uses the same MDSS/DPU/DSI
> + hardware as QCM2290 (DPU 6.5) and shares the same register layout.
>
> $ref: /schemas/display/msm/mdss-common.yaml#
>
> +select:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - qcom,qcm2290-mdss
> + required:
> + - compatible
Why do you need this?
> +
> properties:
> compatible:
> - const: qcom,qcm2290-mdss
> + oneOf:
> + - const: qcom,qcm2290-mdss
> + - items:
> + - const: qcom,shikra-mdss
> + - const: qcom,qcm2290-mdss
>
> clocks:
> items:
> @@ -52,7 +67,11 @@ patternProperties:
>
> properties:
> compatible:
> - const: qcom,qcm2290-dpu
> + oneOf:
> + - const: qcom,qcm2290-dpu
> + - items:
> + - const: qcom,shikra-dpu
> + - const: qcom,qcm2290-dpu
>
> "^dsi@[0-9a-f]+$":
> type: object
> @@ -60,9 +79,14 @@ patternProperties:
>
> properties:
> compatible:
> - items:
> - - const: qcom,qcm2290-dsi-ctrl
> - - const: qcom,mdss-dsi-ctrl
> + oneOf:
> + - items:
> + - const: qcom,qcm2290-dsi-ctrl
> + - const: qcom,mdss-dsi-ctrl
> + - items:
> + - const: qcom,shikra-dsi-ctrl
> + - const: qcom,qcm2290-dsi-ctrl
> + - const: qcom,mdss-dsi-ctrl
Change this to contains:qcom,qcm2290-dsi-ctrl
>
> "^phy@[0-9a-f]+$":
> type: object
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/3] arm64: defconfig: Enable ILI7807S DSI panel driver
From: Krzysztof Kozlowski @ 2026-06-04 12:53 UTC (permalink / raw)
To: Nabige Aala, Rob Clark, Dmitry Baryshkov, Abhinav Kumar,
Jessica Zhang, Sean Paul, Marijn Suijten, David Airlie,
Simona Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Krishna Manikandan, Loic Poulain, Bjorn Andersson, Konrad Dybcio,
Will Deacon, Robin Murphy, Joerg Roedel (AMD)
Cc: linux-arm-msm, dri-devel, freedreno, devicetree, linux-kernel,
iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-2-b3c1b2b67edc@oss.qualcomm.com>
On 04/06/2026 14:30, Nabige Aala wrote:
> Enable the ILI7807S 1080x1920 video-mode DSI panel driver as a module,
> used on the Shikra CQM EVK board.
Does Samsung Shikra CQM EVK have it? I guess no.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH v2 2/3] arm64: defconfig: Enable ILI7807S DSI panel driver
From: Dmitry Baryshkov @ 2026-06-04 12:54 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-2-b3c1b2b67edc@oss.qualcomm.com>
On Thu, Jun 04, 2026 at 06:00:48PM +0530, Nabige Aala wrote:
> Enable the ILI7807S 1080x1920 video-mode DSI panel driver as a module,
> used on the Shikra CQM EVK board.
>
> Signed-off-by: Nabige Aala <nabige.aala@oss.qualcomm.com>
> ---
> arch/arm64/configs/defconfig | 1 +
> 1 file changed, 1 insertion(+)
>
Move it to the series adding corresponding panel driver.
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v6 0/4] Switch Arm SMCCC firmware services to an SMCCC bus
From: Aneesh Kumar K.V @ 2026-06-04 12:58 UTC (permalink / raw)
To: gregkh, linux-coco, linux-arm-kernel, linux-kernel
Cc: Catalin Marinas, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Sudeep Holla, Will Deacon,
Steven Price, Suzuki K Poulose
In-Reply-To: <20260527100233.428018-1-aneesh.kumar@kernel.org>
Hi Greg,
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> writes:
> As discussed here:
> https://lore.kernel.org/all/20250728135216.48084-12-aneesh.kumar@kernel.org
>
> The earlier CCA guest support used an arm-cca-dev platform device as a pure
> software anchor for the TSM class device. That platform device did not
> correspond to a DT/ACPI described device, MMIO range, interrupt, or other
> platform resource; it existed only to make the CCA guest driver bind and to
> place the resulting TSM device in the driver model. The same pattern also
> exists for smccc_trng. Creating separate platform devices for such
> SMCCC-discovered features is misleading, because those features are not
> independent platform devices.
>
> This series adds an Arm SMCCC bus for services discovered through the SMCCC
> firmware interface. The bus provides SMCCC device and driver registration
> helpers, name-based matching, uevent modalias generation, and a sysfs modalias
> attribute. SMCCC service drivers can use MODULE_DEVICE_TABLE(arm_smccc, ...)
> to emit arm_smccc:<name> aliases, allowing userspace to autoload service
> drivers when the SMCCC core registers matching firmware-service devices.
>
> The series then moves SMCCC TRNG and the Arm CCA guest RSI service off the
> platform bus. When the SMCCC core discovers the corresponding firmware
> service, it registers an arm-smccc device for that service. The hwrng
> arm_smccc_trng driver and the Arm CCA guest TSM provider are converted to
> SMCCC drivers that bind to those discovered devices.
>
> The old arm-cca-dev platform device has also been used by userspace as a Realm
> guest indicator. Removing it without a replacement would leave userspace
> depending on an internal driver-binding device. This series therefore adds
> /sys/firmware/cca/realm_guest as a stable, architecture-provided ABI for
> detecting whether the kernel is running as an Arm CCA Realm guest, and then
> removes the dummy arm-cca-dev platform-device registration.
>
Gentle ping. Based on your feedback in [1], I reworked the series to use
an SMCCC bus, with smccc-trng and arm-cca-dev represented as devices on
that bus. Could you let me know whether this approach addresses your
concerns?
[1] https://lore.kernel.org/all/2026051451-comfort-museum-4d2a@gregkh/
-aneesh
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Sanitise host vCPU fields in flush_hyp_vcpu()
From: Fuad Tabba @ 2026-06-04 13:01 UTC (permalink / raw)
To: Hyunwoo Kim
Cc: maz, oupton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm
In-Reply-To: <aiFe-CXo-XVTFz1g@v4bel>
Hi Hyunwoo,
On Thu, 4 Jun 2026 at 12:18, Hyunwoo Kim <imv4bel@gmail.com> wrote:
>
> flush_hyp_vcpu() copies the host vCPU context and vGIC state into the
> hyp's private vCPU on every run. ctxt_to_vcpu() expects a guest context
> to have a NULL __hyp_running_vcpu, which is only ever set on the host
> context, so that it resolves the vCPU via container_of(). The vGIC list
> register save and restore expect used_lrs to stay within the number of
> implemented list registers. While this is generally the case,
> flush_hyp_vcpu() copies both fields verbatim from the host vCPU and
> enforces neither expectation.
>
> Fix by clearing __hyp_running_vcpu and clamping used_lrs after the copy.
Nice catch, both fixes are correct.
Please split this into two patches, one per field. They are independent
bugs that just happen to share a Fixes: tag and the function. Both are
host -> EL2, so worth stating that in the commit messages.
Otherwise this looks right to me.
Cheers,
/fuad
>
> Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
> Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> ---
> arch/arm64/kvm/hyp/nvhe/hyp-main.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 06db299c37a89..ef9318ff0c25e 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -7,6 +7,7 @@
> #include <hyp/adjust_pc.h>
> #include <hyp/switch.h>
>
> +#include <asm/arch_gicv3.h>
> #include <asm/pgtable-types.h>
> #include <asm/kvm_asm.h>
> #include <asm/kvm_emulate.h>
> @@ -128,6 +129,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
>
> hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
>
> + /* A guest context must keep a NULL __hyp_running_vcpu. */
> + hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
> +
> hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
> hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
> hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
> @@ -139,6 +143,13 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
>
> hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
>
> + /* Bound the host-provided used_lrs by the implemented list registers. */
> + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
> + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
> + min_t(unsigned int,
> + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
> + (read_gicreg(ICH_VTR_EL2) & 0xf) + 1);
> +
> hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
> }
>
> --
> 2.43.0
>
>
^ permalink raw reply
* Re: [PATCH v2 0/3] Subject: [PATCH 0/3] Add Shikra (QCM2390) display support
From: Dmitry Baryshkov @ 2026-06-04 13:03 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-0-b3c1b2b67edc@oss.qualcomm.com>
On Thu, Jun 04, 2026 at 06:00:46PM +0530, Nabige Aala wrote:
[PATCH v2 0/3] Subject: [PATCH 0/3] Add Shikra (QCM2390) display support
The subject line is wrong. Please use the tools properly (I'd strongly
recommend using the b4 tool).
--
With best wishes
Dmitry
^ permalink raw reply
* Re: [PATCH v2 3/3] soc: qcom: ubwc: Add Shikra UBWC config
From: Dmitry Baryshkov @ 2026-06-04 13:04 UTC (permalink / raw)
To: Nabige Aala
Cc: Rob Clark, Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang,
Sean Paul, Marijn Suijten, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Krishna Manikandan,
Loic Poulain, Bjorn Andersson, Konrad Dybcio, Will Deacon,
Robin Murphy, Joerg Roedel (AMD), linux-arm-msm, dri-devel,
freedreno, devicetree, linux-kernel, iommu, linux-arm-kernel
In-Reply-To: <20260604-shikra-display-v2-3-b3c1b2b67edc@oss.qualcomm.com>
On Thu, Jun 04, 2026 at 06:00:49PM +0530, Nabige Aala wrote:
> Add UBWC configuration for the Shikra platform. Shikra shares the
> same hardware as QCM2290 (Agatti), so reuse qcm2290_data for the
> UBWC settings
>
> Signed-off-by: Nabige Aala <nabige.aala@oss.qualcomm.com>
> ---
> drivers/soc/qcom/ubwc_config.c | 1 +
> 1 file changed, 1 insertion(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
--
With best wishes
Dmitry
^ permalink raw reply
* [PATCH] arm64/cpufeature: Simplify data output in c_show()
From: Markus Elfring @ 2026-06-04 13:19 UTC (permalink / raw)
To: linux-arm-kernel, Catalin Marinas, Mark Brown, Will Deacon,
Yeoreum Yun, Yicong Yang
Cc: LKML, kernel-janitors
From: Markus Elfring <elfring@users.sourceforge.net>
Date: Thu, 4 Jun 2026 15:13:00 +0200
Move the specification for a line break from a seq_puts() call
to a seq_printf() call.
The source code was transformed by using the Coccinelle software.
Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
arch/arm64/kernel/cpuinfo.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index d50e2a9b066b..a9704a11de57 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -272,10 +272,8 @@ static int c_show(struct seq_file *m, void *v)
if (cpu_have_feature(j))
seq_printf(m, " %s", hwcap_str[j]);
}
- seq_puts(m, "\n");
- seq_printf(m, "CPU implementer\t: 0x%02x\n",
- MIDR_IMPLEMENTOR(midr));
+ seq_printf(m, "\nCPU implementer\t: 0x%02x\n", MIDR_IMPLEMENTOR(midr));
seq_puts(m, "CPU architecture: 8\n");
seq_printf(m, "CPU variant\t: 0x%x\n", MIDR_VARIANT(midr));
seq_printf(m, "CPU part\t: 0x%03x\n", MIDR_PARTNUM(midr));
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Aneesh Kumar K.V @ 2026-06-04 13:26 UTC (permalink / raw)
To: Sudeep Holla
Cc: linux-coco, linux-arm-kernel, linux-kernel, Catalin Marinas,
Sudeep Holla, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Will Deacon, Steven Price,
Suzuki K Poulose
In-Reply-To: <20260603-determined-bumblebee-of-promise-e633d6@sudeepholla>
Sudeep Holla <sudeep.holla@kernel.org> writes:
...
> +static const struct smccc_device_info smccc_devices[] __initconst = {
> + {
> + .func_id = ARM_SMCCC_TRNG_VERSION,
> + .requires_smc = false,
> + .min_return = ARM_SMCCC_TRNG_MIN_VERSION,
> + .device_name = "arm-smccc-trng",
> + },
> +};
> +
> +static bool __init
> +smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
> +{
> + struct arm_smccc_res res;
> + unsigned long ret;
> +
> + if (!IS_ENABLED(CONFIG_ARM64))
> + return false;
> +
> + if (smccc_conduit == SMCCC_CONDUIT_NONE)
> + return false;
> +
> + if (smccc_dev->requires_smc && smccc_conduit != SMCCC_CONDUIT_SMC)
> + return false;
> +
> + arm_smccc_1_1_invoke(smccc_dev->func_id, &res);
> + ret = res.a0;
> +
> + if ((s32)ret < 0)
> + return false;
> +
> + return ret >= smccc_dev->min_return;
> +}
> +
>
I am not sure we want the check to be as simple as ret < 0. Some
function IDs may return input errors based on the supplied arguments
(for example, RMI_ERROR_INPUT). In those cases, we would likely want
this to be handled via a callback.
We also want to use conditional compilation for some function IDs.
Given the callback approach and the #ifdefs, I wonder whether what we
currently have is actually simpler and more flexible.”
> void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
> {
> struct arm_smccc_res res;
> @@ -31,7 +68,7 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
> smccc_version = version;
> smccc_conduit = conduit;
>
> - smccc_trng_available = smccc_probe_trng();
> + smccc_trng_available = smccc_probe_smccc_device(&smccc_devices[0]);
>
> if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
> (smccc_conduit != SMCCC_CONDUIT_NONE)) {
> @@ -241,14 +278,20 @@ subsys_initcall(arm_smccc_bus_init);
>
> static int __init smccc_devices_init(void)
> {
> - struct platform_device *pdev;
> -
> - if (smccc_trng_available) {
> - pdev = platform_device_register_simple("smccc_trng", -1,
> - NULL, 0);
> - if (IS_ERR(pdev))
> - pr_err("smccc_trng: could not register device: %ld\n",
> - PTR_ERR(pdev));
> + const struct smccc_device_info *smccc_dev;
> + struct arm_smccc_device *sdev;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(smccc_devices); i++) {
> + smccc_dev = &smccc_devices[i];
> +
> + if (!smccc_probe_smccc_device(smccc_dev))
> + continue;
> +
> + sdev = arm_smccc_device_register(smccc_dev->device_name);
> + if (IS_ERR(sdev))
> + pr_err("%s: could not register device: %ld\n",
> + smccc_dev->device_name, PTR_ERR(sdev));
> }
>
> return 0;
>
-aneesh
^ permalink raw reply
* Re: [PATCH v2 3/4] arm64: dts: ti: k3-am67a-beagley-ai: Add overlay for IMX219 on CSI0
From: Andrew Davis @ 2026-06-04 13:29 UTC (permalink / raw)
To: Nishanth Menon, Jai Luthra
Cc: Vignesh Raghavendra, Tero Kristo, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Robert Nelson, Devarsh Thakkar,
Tomi Valkeinen, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260529150119.dqzzruc7xqliftwp@bullhorn>
On 5/29/26 10:01 AM, Nishanth Menon wrote:
> On 06:46-20260515, Jai Luthra wrote:
>> RPi v2 Camera (IMX219) is an 8MP camera that can be used with BeagleY AI
>> through the 22-pin CSI-RX connectors. Add a DT overlay to enable use of
>> this camera sensor through the CSI0 connector.
>>
>> Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
>> ---
>> arch/arm64/boot/dts/ti/Makefile | 4 +
>> .../dts/ti/k3-am67a-beagley-ai-csi0-imx219.dtso | 121 +++++++++++++++++++++
>
> Oh man..
> https://lore.kernel.org/linux-arm-kernel/20240702164403.29067-1-afd@ti.com/
> comes to memory.. Afd - what ever happened to that?
>
Good question, others have taken over the torch for the most part. Nice
little talk[0] I found on some current status updates for the topic.
They even mention my little proof of concept around the 19min mark :D but
kinda just dismiss it as it doesn't support hotplug, which is a requirement
for their usecase. But my solution doesn't support hotplug because DT
doesn't support hotplug. And to add that kind of support to DT they are
pushing to change the DTC[1], the FDT format[2] (which hasn't changed in 19
years and is the basis for claiming DT is a firmware/"ABI"), and make an
alternative to DT overlays called "addon DTs"..
What I proposed was something that can work today without any changes
to existing DT infra. My only goal being to prevent needless duplication
in overlays like we see here where you have a new overlay for each
connector the device could be connected to. Just look at our evil vendor
tree to see what this problem can look like, go here[3] and search "fpdlink".
We have 14(!) overlays for just one camera sensor (IMX390) with the only
difference between each being a single line to select the FPD-Link port
where the sensor is connected.
Jai, I see you have already posted v3 of this series, but could you take
a look at what I've proposed here[4] and see if this could be used to make
a single IMX219 overlay that would work for both CSI ports? If you can
pull that off then we avoid the combinatorial explosion of an overlay
for each port on each board for each camera sensor.
Andrew
[0] https://www.youtube.com/watch?v=C8dEQ4OzMnc
[1] https://lore.kernel.org/devicetree-compiler/20260112142009.1006236-1-herve.codina@bootlin.com/
[2] https://lore.kernel.org/devicetree-compiler/20260409115426.352214-1-herve.codina@bootlin.com/
[3] https://git.ti.com/cgit/ti-linux-kernel/ti-linux-kernel/tree/arch/arm64/boot/dts/ti?h=ti-linux-6.18.y
[4] https://lore.kernel.org/linux-arm-kernel/20240702164403.29067-1-afd@ti.com/
> other than the dsi mux, painful to see so much duplication..
>
> Other than that, there is the previous comment (ordering etc, repeated
> here). I also suggest people put the url of the board/part that the
> overlay is supposed to refer to when creating overlays.. at least, some
> sort of canonical link so folks are'nt confused in a future date.
>
>
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Sanitise host vCPU fields in flush_hyp_vcpu()
From: Hyunwoo Kim @ 2026-06-04 13:35 UTC (permalink / raw)
To: Fuad Tabba
Cc: maz, oupton, joey.gouly, seiden, suzuki.poulose, yuzenghui,
catalin.marinas, will, linux-arm-kernel, kvmarm, imv4bel
In-Reply-To: <CA+EHjTwgPFbbp7khcy+DZ9HZWCX-OWPfO78Gj_eQuCoj+SA90g@mail.gmail.com>
On Thu, Jun 04, 2026 at 02:01:17PM +0100, Fuad Tabba wrote:
> Hi Hyunwoo,
>
> On Thu, 4 Jun 2026 at 12:18, Hyunwoo Kim <imv4bel@gmail.com> wrote:
> >
> > flush_hyp_vcpu() copies the host vCPU context and vGIC state into the
> > hyp's private vCPU on every run. ctxt_to_vcpu() expects a guest context
> > to have a NULL __hyp_running_vcpu, which is only ever set on the host
> > context, so that it resolves the vCPU via container_of(). The vGIC list
> > register save and restore expect used_lrs to stay within the number of
> > implemented list registers. While this is generally the case,
> > flush_hyp_vcpu() copies both fields verbatim from the host vCPU and
> > enforces neither expectation.
> >
> > Fix by clearing __hyp_running_vcpu and clamping used_lrs after the copy.
>
> Nice catch, both fixes are correct.
Thanks for the review.
>
> Please split this into two patches, one per field. They are independent
> bugs that just happen to share a Fixes: tag and the function. Both are
> host -> EL2, so worth stating that in the commit messages.
I'll split this into two patches and resend it as a series.
>
> Otherwise this looks right to me.
>
> Cheers,
> /fuad
>
>
> >
> > Fixes: be66e67f1750 ("KVM: arm64: Use the pKVM hyp vCPU structure in handle___kvm_vcpu_run()")
> > Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
> > ---
> > arch/arm64/kvm/hyp/nvhe/hyp-main.c | 11 +++++++++++
> > 1 file changed, 11 insertions(+)
> >
> > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > index 06db299c37a89..ef9318ff0c25e 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > @@ -7,6 +7,7 @@
> > #include <hyp/adjust_pc.h>
> > #include <hyp/switch.h>
> >
> > +#include <asm/arch_gicv3.h>
> > #include <asm/pgtable-types.h>
> > #include <asm/kvm_asm.h>
> > #include <asm/kvm_emulate.h>
> > @@ -128,6 +129,9 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
> >
> > hyp_vcpu->vcpu.arch.ctxt = host_vcpu->arch.ctxt;
> >
> > + /* A guest context must keep a NULL __hyp_running_vcpu. */
> > + hyp_vcpu->vcpu.arch.ctxt.__hyp_running_vcpu = NULL;
> > +
> > hyp_vcpu->vcpu.arch.mdcr_el2 = host_vcpu->arch.mdcr_el2;
> > hyp_vcpu->vcpu.arch.hcr_el2 &= ~(HCR_TWI | HCR_TWE);
> > hyp_vcpu->vcpu.arch.hcr_el2 |= READ_ONCE(host_vcpu->arch.hcr_el2) &
> > @@ -139,6 +143,13 @@ static void flush_hyp_vcpu(struct pkvm_hyp_vcpu *hyp_vcpu)
> >
> > hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3 = host_vcpu->arch.vgic_cpu.vgic_v3;
> >
> > + /* Bound the host-provided used_lrs by the implemented list registers. */
> > + if (static_branch_unlikely(&kvm_vgic_global_state.gicv3_cpuif))
> > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs =
> > + min_t(unsigned int,
> > + hyp_vcpu->vcpu.arch.vgic_cpu.vgic_v3.used_lrs,
> > + (read_gicreg(ICH_VTR_EL2) & 0xf) + 1);
> > +
> > hyp_vcpu->vcpu.arch.pid = host_vcpu->arch.pid;
> > }
> >
> > --
> > 2.43.0
> >
> >
Best regards,
Hyunwoo Kim
^ permalink raw reply
* Re: [PATCH net-next v6 1/2] net: ti: icssg-prueth: Add Frame Preemption MAC Merge support
From: Meghana Malladi @ 2026-06-04 13:37 UTC (permalink / raw)
To: Maxime Chevallier, liuhangbin, h-mittal1, haokexin,
vadim.fedorenko, devnexen, horms, jacob.e.keller, arnd, afd,
basharath, parvathi, vladimir.oltean, rogerq, danishanwar, pabeni,
kuba, edumazet, davem, andrew+netdev
Cc: linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <de0255c8-d751-4220-b0ab-88aef3a15f9a@bootlin.com>
Hi Maxime,
On 5/26/26 00:48, Maxime Chevallier wrote:
> Hi Meghana,
>
> On 5/25/26 20:26, Meghana Malladi wrote:
>> From: MD Danish Anwar <danishanwar@ti.com>
>>
>> Introduce QoS infrastructure for Frame Preemption (FPE) support in
>> the ICSSG Ethernet driver.
>>
>> prueth_qos_iet tracks FPE enable/active state and verify state machine
>> status via firmware-reported enum icssg_ietfpe_verify_states.
>> icssg_config_ietfpe() configures IET FPE in firmware, triggers
>> verify state machine based on ethtool MAC Merge parameters.
>> Polls firmware verify status up to 3 times with verify_time_ms intervals
>> and driver handles timeout by logging error and returning.
>> In case of any failure during configuration for enable/disable,
>> IET FPE falls back to disabled state.
>>
>> For MQPRIO qdisc support all queues are express by default later
>> gets override by user-provided preemptible_tcs bitmask via tc qdisc mask
>> Preempt mask configuration: Maps traffic classes to queue express/
>> preemptible
>> state and applied only when FPE is active (Tx enabled)
>>
>> Verify state machine re-triggers on link up/down events based on
>> fpe_enabled and fpe_active flags, and for memory protection, fpe_lock
>> serializes all FPE state mutations, preventing races between ethtool
>> config, qdisc setup, and link events
>>
>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi@ti.com>
>
> There's quite a lot of checkpatch output for this patch, I'll let you
> browse through it :)
>
> Also keep in mind that we still recommend 80 chars on net.
>
I aim to keep lines under 80 characters, unless it compromises
readability. I'll review and see if further adjustments can be made :)
> Besides that, I have a few comments, see below :)
>
>> ---
>>
>> v6-v5:
>> - Balance fpe_lock mutex lifecycle on all error paths
>> - Remove deadcode inside icssg_iet_set_preempt_mask()
>> - Add fallback label inside icssg_config_ietfpe() to fix
>> stale state machine handling.
>> - Replace netdev_err with netdev_info and netdev_dbg wherever
>> applicable
>> - Remove EXPORT_SYMBOL_GPL for icssg_config_ietfpe()
>> - Remove redundant code inside icssg_qos_init()
>> - qdisc deletion path clears per-queue map as well.
>> - Protect all read/writes to p_mqprio with a mutex
>> All the above changes address the comments raised by sashiko
>>
>> drivers/net/ethernet/ti/Makefile | 3 +-
>> drivers/net/ethernet/ti/icssg/icssg_common.c | 1 +
>> drivers/net/ethernet/ti/icssg/icssg_config.h | 9 -
>> drivers/net/ethernet/ti/icssg/icssg_prueth.c | 6 +
>> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 2 +
>> drivers/net/ethernet/ti/icssg/icssg_qos.c | 269 +++++++++++++++++++
>> drivers/net/ethernet/ti/icssg/icssg_qos.h | 66 +++++
>> 7 files changed, 346 insertions(+), 10 deletions(-)
>> create mode 100644 drivers/net/ethernet/ti/icssg/icssg_qos.c
>> create mode 100644 drivers/net/ethernet/ti/icssg/icssg_qos.h
>>
>> diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/
>> ti/Makefile
>> index f4276c9a77620..d19bcd25c9d07 100644
>> --- a/drivers/net/ethernet/ti/Makefile
>> +++ b/drivers/net/ethernet/ti/Makefile
>> @@ -46,6 +46,7 @@ icssg-y := icssg/icssg_common.o \
>> icssg/icssg_config.o \
>> icssg/icssg_mii_cfg.o \
>> icssg/icssg_stats.o \
>> - icssg/icssg_ethtool.o
>> + icssg/icssg_ethtool.o \
>> + icssg/icssg_qos.o
>> obj-$(CONFIG_TI_ICSS_IEP) += icssg/icss_iep.o
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/
>> net/ethernet/ti/icssg/icssg_common.c
>> index a28a608f9bf4b..c3ee97e96cd50 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_common.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
>> @@ -1724,6 +1724,7 @@ void prueth_netdev_exit(struct prueth *prueth,
>> netif_napi_del(&emac->napi_rx);
>> + mutex_destroy(&emac->qos.iet.fpe_lock);
>> pruss_release_mem_region(prueth->pruss, &emac->dram);
>> free_netdev(emac->ndev);
>> prueth->emac[mac] = NULL;
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/
>> net/ethernet/ti/icssg/icssg_config.h
>> index 60d69744ffae2..1ac202f855ed4 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_config.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h
>> @@ -323,13 +323,4 @@ struct prueth_fdb_slot {
>> u8 fid;
>> u8 fid_c2;
>> } __packed;
>> -
>> -enum icssg_ietfpe_verify_states {
>> - ICSSG_IETFPE_STATE_UNKNOWN = 0,
>> - ICSSG_IETFPE_STATE_INITIAL,
>> - ICSSG_IETFPE_STATE_VERIFYING,
>> - ICSSG_IETFPE_STATE_SUCCEEDED,
>> - ICSSG_IETFPE_STATE_FAILED,
>> - ICSSG_IETFPE_STATE_DISABLED
>> -};
>> #endif /* __NET_TI_ICSSG_CONFIG_H */
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/
>> net/ethernet/ti/icssg/icssg_prueth.c
>> index 591be5c8056b4..39f379df923bf 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
>> @@ -392,6 +392,8 @@ static void emac_adjust_link(struct net_device *ndev)
>> } else {
>> icssg_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE);
>> }
>> +
>> + icssg_qos_link_state_update(ndev);
>> }
>> if (emac->link) {
>> @@ -1652,6 +1654,7 @@ static const struct net_device_ops
>> emac_netdev_ops = {
>> .ndo_hwtstamp_get = icssg_ndo_get_ts_config,
>> .ndo_hwtstamp_set = icssg_ndo_set_ts_config,
>> .ndo_xsk_wakeup = prueth_xsk_wakeup,
>> + .ndo_setup_tc = icssg_qos_ndo_setup_tc,
>> };
>> static int prueth_netdev_init(struct prueth *prueth,
>> @@ -1686,6 +1689,8 @@ static int prueth_netdev_init(struct prueth
>> *prueth,
>> INIT_DELAYED_WORK(&emac->stats_work, icssg_stats_work_handler);
>> + icssg_qos_init(ndev);
>> +
>> ret = pruss_request_mem_region(prueth->pruss,
>> port == PRUETH_PORT_MII0 ?
>> PRUSS_MEM_DRAM0 : PRUSS_MEM_DRAM1,
>> @@ -1793,6 +1798,7 @@ static int prueth_netdev_init(struct prueth
>> *prueth,
>> free:
>> pruss_release_mem_region(prueth->pruss, &emac->dram);
>> free_ndev:
>> + mutex_destroy(&emac->qos.iet.fpe_lock);
>> emac->ndev = NULL;
>> prueth->emac[mac] = NULL;
>> free_netdev(ndev);
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/
>> net/ethernet/ti/icssg/icssg_prueth.h
>> index df93d15c5b786..85f7017d2c8e7 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> @@ -44,6 +44,7 @@
>> #include "icssg_config.h"
>> #include "icss_iep.h"
>> #include "icssg_switch_map.h"
>> +#include "icssg_qos.h"
>> #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN)
>> #define PRUETH_MIN_PKT_SIZE (VLAN_ETH_ZLEN)
>> @@ -254,6 +255,7 @@ struct prueth_emac {
>> struct bpf_prog *xdp_prog;
>> struct xdp_attachment_info xdpi;
>> int xsk_qid;
>> + struct prueth_qos qos;
>> };
>> /* The buf includes headroom compatible with both skb and xdpf */
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.c b/drivers/net/
>> ethernet/ti/icssg/icssg_qos.c
>> new file mode 100644
>> index 0000000000000..2781abf39e9bb
>> --- /dev/null
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_qos.c
>> @@ -0,0 +1,269 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Texas Instruments ICSSG PRUETH QoS submodule
>> + * Copyright (C) 2023 Texas Instruments Incorporated - http://
>> www.ti.com/
>> + */
>> +
>> +#include "icssg_prueth.h"
>> +#include "icssg_switch_map.h"
>> +
>> +static void icssg_iet_set_preempt_mask(struct prueth_emac *emac)
>> +{
>> + void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
>> + struct prueth_qos_mqprio *p_mqprio = &emac->qos.mqprio;
>> + struct tc_mqprio_qopt *qopt = &p_mqprio->mqprio.qopt;
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int prempt_mask = 0, i;
>> + u8 tc, num_tc;
>> +
>> + if (!iet->preemptible_tcs)
>> + goto reset_hw;
>> +
>> + if (iet->fpe_active) {
>> + /* Configure the queues based on the preemptible tc map set
>> by the user */
>> + num_tc = p_mqprio->mqprio.qopt.num_tc;
>> + for (tc = 0; tc < num_tc; tc++) {
>> + /* check if the tc is preemptive or not */
>> + if (iet->preemptible_tcs & BIT(tc)) {
>> + for (i = qopt->offset[tc]; i < qopt->offset[tc] +
>> qopt->count[tc]; i++) {
>> + /* Set all the queues in this tc as preemptive
>> queues */
>> + writeb(BIT(4), config + EXPRESS_PRE_EMPTIVE_Q_MAP
>> + i);
>> + }
>> + } else {
>> + /* Set all the queues in this tc as express queues */
>> + for (i = qopt->offset[tc]; i < qopt->offset[tc] +
>> qopt->count[tc]; i++) {
>> + writeb(0, config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
>> + prempt_mask |= BIT(i);
>> + }
>> + }
>> + netdev_set_tc_queue(emac->ndev, tc, qopt->count[tc],
>> qopt->offset[tc]);
>> + }
>> + writeb(prempt_mask, config + EXPRESS_PRE_EMPTIVE_Q_MASK);
>> + return;
>> + }
>> +
>> +reset_hw:
>> + /* Reset to default: all queues as express */
>> + for (i = 0; i < ICSSG_MAX_TC_QUEUES; i++)
>> + writeb(0, config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
>> + writeb(ICSSG_EXPRESS_Q_MASK_ALL, config +
>> EXPRESS_PRE_EMPTIVE_Q_MASK);
>> +}
>> +
>> +static int icssg_iet_verify_wait(struct prueth_emac *emac)
>> +{
>> + void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int try = 3;
>> +
>> + do {
>> + msleep(iet->verify_time_ms);
>> + iet->verify_status = readb(config + PRE_EMPTION_VERIFY_STATUS);
>> + if (iet->verify_status == ICSSG_IETFPE_STATE_SUCCEEDED)
>> + return 0;
>> + } while (--try > 0);
>
> You can replace that whole loop with a readb_poll_timeout, to avoid
> open-coding it.
>
Sure will do that.
>> +
>> + netdev_err(emac->ndev, "MAC Verify timeout\n");
>> + return -ETIMEDOUT;
>> +}
>> +
>> +/* Direct synchronous configuration of IET FPE.
>> + * Caller must hold iet->fpe_lock.
>> + */
>> +int icssg_config_ietfpe(struct net_device *ndev, bool enable)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int ret;
>> + u8 val;
>> +
>> + lockdep_assert_held(&iet->fpe_lock);
>> +
>> + if (!netif_running(ndev)) {
>> + netdev_dbg(ndev, "cannot change IET/FPE state when interface
>> is down\n");
>> + return 0;
>> + }
>> +
>> + /* Update FPE Tx enable bit (PRE_EMPTION_ENABLE_TX) if
>> + * fpe_enabled is set to enable MM in Tx direction
>> + */
>> + writeb(enable ? 1 : 0, config + PRE_EMPTION_ENABLE_TX);
>> +
>> + /* If FPE is to be enabled, first configure MAC Verify state
>> + * machine in firmware as firmware kicks the Verify process
>> + * as soon as ICSSG_EMAC_PORT_PREMPT_TX_ENABLE command is
>> + * received.
>> + */
>> + if (enable && iet->mac_verify_configure) {
>> + writeb(1, config + PRE_EMPTION_ENABLE_VERIFY);
>> + writew(iet->tx_min_frag_size + ETH_FCS_LEN,
>> + config + PRE_EMPTION_ADD_FRAG_SIZE_LOCAL);
>> + writel(iet->verify_time_ms, config + PRE_EMPTION_VERIFY_TIME);
>> + } else {
>> + writeb(0, config + PRE_EMPTION_ENABLE_VERIFY);
>> + iet->verify_status = ICSSG_IETFPE_STATE_DISABLED;
>> + }
>> +
>> + /* Send command to enable FPE Tx side. Rx is always enabled */
>> + ret = icssg_set_port_state(emac,
>> + enable ? ICSSG_EMAC_PORT_PREMPT_TX_ENABLE :
>> + ICSSG_EMAC_PORT_PREMPT_TX_DISABLE);
>> + if (ret) {
>> + netdev_err(ndev, "TX preempt %s command failed\n",
>> + str_enable_disable(enable));
>> + goto fallback;
>> + }
>> +
>> + if (enable && iet->mac_verify_configure) {
>> + ret = icssg_iet_verify_wait(emac);
>> + if (ret) {
>> + netdev_err(ndev, "MAC Verification failed with timeout\n");
>> + goto disable_tx;
>> + }
>> + } else if (enable) {
>> + /* Give firmware some time to update PRE_EMPTION_ACTIVE_TX
>> state */
>> + usleep_range(100, 200);
>> + }
>> +
>> + if (enable) {
>> + val = readb(config + PRE_EMPTION_ACTIVE_TX);
>> + if (val != 1) {
>> + netdev_err(ndev,
>> + "Firmware fails to activate IET/FPE\n");
>> + ret = -EIO;
>> + goto disable_tx;
>> + }
>> + iet->fpe_active = true;
>> + } else {
>> + iet->fpe_active = false;
>> + }
>> +
>> + icssg_iet_set_preempt_mask(emac);
>> + netdev_info(ndev, "IET FPE %s successfully\n",
>> + str_enable_disable(iet->fpe_active));
>> + return ret;
>> +
>> +disable_tx:
>> + icssg_set_port_state(emac, ICSSG_EMAC_PORT_PREMPT_TX_DISABLE);
>> +fallback:
>> + writeb(0, config + PRE_EMPTION_ENABLE_TX);
>> + writeb(0, config + PRE_EMPTION_ENABLE_VERIFY);
>> + iet->verify_status = ICSSG_IETFPE_STATE_DISABLED;
>> + iet->fpe_active = false;
>> + return ret;
>> +}
>> +
>> +void icssg_qos_init(struct net_device *ndev)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> +
>> + mutex_init(&iet->fpe_lock);
>> + /* Set default values to prevent garbage values during .get_mm() */
>> + mutex_lock(&iet->fpe_lock);
>> + iet->verify_time_ms = ICSSG_IET_MAX_VERIFY_TIME;
>> + iet->tx_min_frag_size = ETH_ZLEN;
>> + mutex_unlock(&iet->fpe_lock);
>> +}
>> +EXPORT_SYMBOL_GPL(icssg_qos_init);
>> +
>> +static int icssg_iet_change_preemptible_tcs(struct prueth_emac *emac)
>> +{
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int ret;
>> +
>> + mutex_lock(&iet->fpe_lock);
>> + ret = icssg_config_ietfpe(emac->ndev, iet->fpe_enabled);
>> + mutex_unlock(&iet->fpe_lock);
>> +
>> + return ret;
>> +}
>> +
>> +static int emac_tc_query_caps(struct net_device *ndev, void *type_data)
>> +{
>> + struct tc_query_caps_base *base = type_data;
>> +
>> + switch (base->type) {
>> + case TC_SETUP_QDISC_MQPRIO: {
>> + struct tc_mqprio_caps *caps = base->caps;
>> +
>> + caps->validate_queue_counts = true;
>> + return 0;
>> + }
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +}
>> +
>> +static int emac_tc_setup_mqprio(struct net_device *ndev, void
>> *type_data)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + struct prueth_qos_mqprio *p_mqprio = &emac->qos.mqprio;
>> + struct tc_mqprio_qopt_offload *mqprio = type_data;
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int ret;
>> +
>> + /* Validate parameters */
>> + if (mqprio->qopt.num_tc > ICSSG_MAX_TC_QUEUES) {
>> + netdev_err(ndev, "Number of traffic classes (%u) exceeds
>> hardware limit\n",
>> + mqprio->qopt.num_tc);
>> + return -EINVAL;
>> + }
>> +
>> + if (mqprio->flags & TC_MQPRIO_F_SHAPER) {
>> + netdev_err(ndev, "traffic shaping is not supported\n");
>> + return -EINVAL;
>
> Maybe -EOPNOTSUPP ?
>
>> + }
>> +
>> + if (mqprio->flags & (TC_MQPRIO_F_MIN_RATE | TC_MQPRIO_F_MAX_RATE)) {
>> + netdev_err(ndev, "per-queue rate limiting is not supported\n");
>> + return -EINVAL;
>
> Same
>
Will update wherever applicable
>> + }
>> +
>> + if (!mqprio->qopt.num_tc) {
>> + netdev_reset_tc(ndev);
>> + } else {
>> + netdev_set_num_tc(ndev, mqprio->qopt.num_tc);
>> + }
>> +
>> + mutex_lock(&iet->fpe_lock);
>> + if (!mqprio->qopt.num_tc) {
>> + iet->preemptible_tcs = 0;
>> + } else {
>> + memcpy(&p_mqprio->mqprio, mqprio, sizeof(*mqprio));
>> + iet->preemptible_tcs = mqprio->preemptible_tcs;
>> + }
>> + mutex_unlock(&iet->fpe_lock);
>> +
>> + netdev_dbg(ndev, "dev->num_tc %u dev->real_num_tx_queues %u\n",
>> + ndev->num_tc, ndev->real_num_tx_queues);
>> +
>> + ret = icssg_iet_change_preemptible_tcs(emac);
>> + return ret;
>
> Simplify this with :
>
> return icssg_iet_change_preemptible_tcs(emac);
>
Sure.
>> +}
>> +
>> +int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum
>> tc_setup_type type,
>> + void *type_data)
>> +{
>> + switch (type) {
>> + case TC_QUERY_CAPS:
>> + return emac_tc_query_caps(ndev, type_data);
>> + case TC_SETUP_QDISC_MQPRIO:
>> + return emac_tc_setup_mqprio(ndev, type_data);
>> + default:
>> + return -EOPNOTSUPP;
>> + }
>> +}
>> +EXPORT_SYMBOL_GPL(icssg_qos_ndo_setup_tc);
>> +
>> +void icssg_qos_link_state_update(struct net_device *ndev)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int ret;
>> +
>> + ret = icssg_iet_change_preemptible_tcs(emac);
>> + if (ret)
>> + netdev_dbg(ndev, "IET FPE %s failed\n",
>> + str_enable_disable(iet->fpe_active));
>> +}
>> +EXPORT_SYMBOL_GPL(icssg_qos_link_state_update);
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.h b/drivers/net/
>> ethernet/ti/icssg/icssg_qos.h
>> new file mode 100644
>> index 0000000000000..9355e96bbcda8
>> --- /dev/null
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h
>> @@ -0,0 +1,66 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/* Copyright (C) 2023 Texas Instruments Incorporated - http://
>> www.ti.com/
>> + */
>> +
>> +#ifndef __NET_TI_ICSSG_QOS_H
>> +#define __NET_TI_ICSSG_QOS_H
>> +
>> +#include <linux/atomic.h>
>> +#include <linux/netdevice.h>
>> +#include <net/pkt_sched.h>
>> +
>> +#define ICSSG_MAX_TC_QUEUES 8
>> +#define ICSSG_EXPRESS_Q_MASK_ALL 0xFF
>> +#define ICSSG_IET_MAX_VERIFY_TIME 128
>> +#define ICSSG_IET_MIN_VERIFY_TIME 1
>> +
>> +/**
>> + * enum icssg_ietfpe_verify_states - status of MAC Merge Verify
>> returned by firmware
>> + * @ICSSG_IETFPE_STATE_UNKNOWN:
>> + * verification status is unknown
>> + * @ICSSG_IETFPE_STATE_INITIAL:
>> + * Firmware returns this if verify state diagram is idle
>> + * @ICSSG_IETFPE_STATE_VERIFYING:
>> + * Firmware returns this if verification is ongoing
>> + * @ICSSG_IETFPE_STATE_SUCCEEDED:
>> + * Firmware returns this if verify state diagram completes
>> verification
>> + * @ICSSG_IETFPE_STATE_FAILED:
>> + * Firmware returns this if verify state diagram fails during
>> verification
>> + * @ICSSG_IETFPE_STATE_DISABLED:
>> + * verification is disabled by the driver
>> + */
>> +enum icssg_ietfpe_verify_states {
>> + ICSSG_IETFPE_STATE_UNKNOWN = 0,
>> + ICSSG_IETFPE_STATE_INITIAL,
>> + ICSSG_IETFPE_STATE_VERIFYING,
>> + ICSSG_IETFPE_STATE_SUCCEEDED,
>> + ICSSG_IETFPE_STATE_FAILED,
>> + ICSSG_IETFPE_STATE_DISABLED
>> +};
>> +
>> +struct prueth_qos_mqprio {
>> + struct tc_mqprio_qopt_offload mqprio;
>> +};
>> +
>> +struct prueth_qos_iet {
>> + bool fpe_enabled;
>> + bool mac_verify_configure;
>> + u32 tx_min_frag_size;
>> + u32 verify_time_ms;
>> + bool fpe_active;
>> + enum icssg_ietfpe_verify_states verify_status;
>> + struct mutex fpe_lock;
>
> Checkpatch already says it, but you need to document what this
> mutex is protecting.
>
Wasn't actually aware of this, will fix it in v7
>> + u8 preemptible_tcs;
>> +};
>> +
>> +struct prueth_qos {
>> + struct prueth_qos_iet iet;
>> + struct prueth_qos_mqprio mqprio;
>> +};
>> +
>> +void icssg_qos_init(struct net_device *ndev);
>> +void icssg_qos_link_state_update(struct net_device *ndev);
>> +int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum
>> tc_setup_type type,
>> + void *type_data);
>> +int icssg_config_ietfpe(struct net_device *ndev, bool enable);
>> +#endif /* __NET_TI_ICSSG_QOS_H */
>
> Thanks,
>
> Maxime
^ permalink raw reply
* Re: [PATCH net-next v6 1/2] net: ti: icssg-prueth: Add Frame Preemption MAC Merge support
From: Meghana Malladi @ 2026-06-04 13:37 UTC (permalink / raw)
To: Andrew Lunn, Maxime Chevallier
Cc: liuhangbin, haokexin, vadim.fedorenko, devnexen, horms,
jacob.e.keller, arnd, afd, basharath, parvathi, vladimir.oltean,
rogerq, danishanwar, pabeni, kuba, edumazet, davem, andrew+netdev,
linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <ac753d51-0a1b-4fda-aae3-661ca5b8715c@lunn.ch>
On 5/26/26 01:16, Andrew Lunn wrote:
>>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>>> @@ -44,6 +44,7 @@
>>> #include "icssg_config.h"
>>> #include "icss_iep.h"
>>> #include "icssg_switch_map.h"
>>> +#include "icssg_qos.h"
>>> #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN)
>
> Sorry for hijacking another message, but the indentation looks odd
> here.
>
Sure will fix this, thanks for catching
> Andrew
^ permalink raw reply
* Re: [PATCH net-next v6 0/2] Add Frame Preemption MAC Merge support for ICSSG
From: Meghana Malladi @ 2026-06-04 13:39 UTC (permalink / raw)
To: Simon Horman
Cc: liuhangbin, haokexin, vadim.fedorenko, devnexen, jacob.e.keller,
arnd, afd, basharath, parvathi, vladimir.oltean, rogerq,
danishanwar, pabeni, kuba, edumazet, davem, andrew+netdev,
linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <20260527115755.GK2256768@horms.kernel.org>
Hi Simon,
On 5/27/26 17:27, Simon Horman wrote:
> On Mon, May 25, 2026 at 11:56:58PM +0530, Meghana Malladi wrote:
>> This patch series adds QoS support to the ICSSG PRUETH driver.
>> The first patch implements mqprio qdisc handling and TC offload hooks
>> so userspace can request TC mappings and queue counts.
>>
>> It also integrates a driver-side mechanism to program the firmware
>> with the IET/FPE preemption mask and to kick the firmware verify state
>> machine when frame preemption is enabled. The second patch adds ethtool
>> perations for the MAC Merge (Frame Preemption) sublayer, exposing .get_mm,
>> .set_mm and .get_mm_stats so admins can view and change MAC Merge
>> parameters and retrieve preemption statistics.
>>
>> v5: https://lore.kernel.org/all/20260430111723.497113-1-m-malladi@ti.com/
>>
>> MD Danish Anwar (2):
>> net: ti: icssg-prueth: Add Frame Preemption MAC Merge support
>> net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge
>
> Hi Meghana and MD,
>
> There is another round of AI-generated reviews for this patch-set available at
> https://netdev-ai.bots.linux.dev/ and https://sashiko.dev/
>
> I would appreciate it if you could look over them and address any
> issues that are either introduced by this patch-set, or directly
> impact it.
>
Yeah I am working on it, though some of them seem to be false positives,
some actually made sense. Hopefully I will fix all of them without
introducing anything new in my next version.
> I would not suggest expanding this patchset to address any other
> pre-existing issues, but rather address them separately as appropriate.
^ permalink raw reply
* Re: [PATCH RFC v3 3/5] clk: zte: Introduce a driver for zx297520v3 top clocks and resets.
From: Philipp Zabel @ 2026-06-04 13:44 UTC (permalink / raw)
To: Stefan Dösinger, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Brian Masney
Cc: linux-clk, devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <7973709.EvYhyI6sBW@strix>
On Mi, 2026-06-03 at 23:49 +0300, Stefan Dösinger wrote:
> Hi,
>
> Thanks for the comments!
>
> Am Mittwoch, 3. Juni 2026, 12:14:21 Ostafrikanische Zeit schrieb Philipp
> Zabel:
>
> > Is this delay long enough for all potential users of reset_control_reset()?
> > Are there actually any at all?
>
> You mean drivers that are in use on this SoC that call reset_control_reset?
Yes.
> Afaics not, they all call reset_assert/reset_deassert, or only ever deassert a
> reset that is set on boot. It isn't called at runtime and the only driver
> calling it that is in use on zx297520v3 is stmmac, which only calls it if
> assert/deassert aren't available.
>
> I implemented the reset() callback because other drivers had it and grabbed
> the magic usleep(100) from ZTE's USB code. It looks like I should just /dev/
> null it.
If it is not used, please just drop it.
The .reset callback exists for self-clearing resets [1]. It's ok to
emulate those in software for the benefit of consumer drivers that have
to work with both types of reset controllers, but I'd like this to be
limited to those case where it's actually needed.
[1] https://docs.kernel.org/driver-api/reset.html#c.reset_control_ops
>
regards
Philipp
^ permalink raw reply
* [PATCH v3] clk: imx: Add audio PLL debugfs for K-divider control
From: Jacky Bai @ 2026-06-04 13:48 UTC (permalink / raw)
To: Abel Vesa, Peng Fan, Michael Turquette, Stephen Boyd,
Brian Masney, Frank Li, Sascha Hauer, Pengutronix Kernel Team,
Fabio Estevam
Cc: linux-clk, imx, linux-arm-kernel, Jacky Bai
Add debugfs support for runtime tuning of the audio PLL K divider,
which enables fine-grained frequency adjustments for audio PLL.
This is used for:
- Audio clock calibration and testing
- Debugging audio synchronization issues
Two debug interfaces are exported to userspace:
- delta_k: It is used to adjust the K divider in PLL based on small
steps
- pll_parameter: It is used for get PLL's current M-divider,
P-divider, S-divider & K-divider setting in PLL register
Signed-off-by: Jacky Bai <ping.bai@nxp.com>
---
Changes in v3:
- update the spinlock scope based on the Sashiko AI and Peng's comment
- Link to v2: https://lore.kernel.org/r/20260519-imx8m_pll_debugfs-v2-1-20e1d88526b0@nxp.com
Changes in v2:
- remove the examples from commit log.
- refine the comments blocks
- add delta_k read back support
- resolve the comments from Sashiko AI
- add prefix to audio_pll_debug_init API
- Link to v1: https://lore.kernel.org/r/20260512-imx8m_pll_debugfs-v1-1-e1e44b21be90@nxp.com
---
drivers/clk/imx/clk-imx8mm.c | 6 +++
drivers/clk/imx/clk-pll14xx.c | 119 +++++++++++++++++++++++++++++++++++++++++-
drivers/clk/imx/clk.h | 1 +
3 files changed, 125 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index 319af4deec01c188524807d39dff92bbd08f3601..89d442415a0108ec9b8af85946403b2612ec4fc7 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -300,6 +300,7 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
+ struct clk_hw *audio_pll_hws[2];
void __iomem *base;
int ret;
@@ -610,6 +611,11 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
imx_register_uart_clocks();
+ /* Add debug interface for audio PLLs */
+ audio_pll_hws[0] = hws[IMX8MM_AUDIO_PLL1];
+ audio_pll_hws[1] = hws[IMX8MM_AUDIO_PLL2];
+ imx_audio_pll_debug_init(audio_pll_hws, ARRAY_SIZE(audio_pll_hws));
+
return 0;
unregister_hws:
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
index 39600ee22be3066683b562aa6f2a8b750d19c4cc..b6f1cc9f570059b7a1e3d1f9655fa40477c75bb7 100644
--- a/drivers/clk/imx/clk-pll14xx.c
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -8,11 +8,13 @@
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
#include <linux/err.h>
#include <linux/export.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/jiffies.h>
#include "clk.h"
@@ -40,6 +42,8 @@ struct clk_pll14xx {
enum imx_pll14xx_type type;
const struct imx_pll14xx_rate_table *rate_table;
int rate_count;
+ s16 delta_k;
+ spinlock_t lock;
};
#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
@@ -134,6 +138,7 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat
u32 pll_div_ctl0, pll_div_ctl1;
int mdiv, pdiv, sdiv, kdiv;
long fout, rate_min, rate_max, dist, best = LONG_MAX;
+ unsigned long flags;
const struct imx_pll14xx_rate_table *tt;
/*
@@ -161,11 +166,16 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat
return;
}
+ spin_lock_irqsave(&pll->lock, flags);
+
pll_div_ctl0 = readl_relaxed(pll->base + DIV_CTL0);
+ pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1);
+
+ spin_unlock_irqrestore(&pll->lock, flags);
+
mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0);
pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0);
sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0);
- pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1);
/* Then see if we can get the desired rate by only adjusting kdiv (glitch free) */
rate_min = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, KDIV_MIN, prate);
@@ -361,11 +371,14 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
struct imx_pll14xx_rate_table rate;
+ unsigned long flags;
u32 gnrl_ctl, div_ctl0;
int ret;
imx_pll14xx_calc_settings(pll, drate, prate, &rate);
+ spin_lock_irqsave(&pll->lock, flags);
+
div_ctl0 = readl_relaxed(pll->base + DIV_CTL0);
if (!clk_pll14xx_mp_change(&rate, div_ctl0)) {
@@ -377,6 +390,8 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv),
pll->base + DIV_CTL1);
+ spin_unlock_irqrestore(&pll->lock, flags);
+
return 0;
}
@@ -396,6 +411,8 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv), pll->base + DIV_CTL1);
+ spin_unlock_irqrestore(&pll->lock, flags);
+
/*
* According to SPEC, t3 - t2 need to be greater than
* 1us and 1/FREF, respectively.
@@ -508,6 +525,8 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
if (!pll)
return ERR_PTR(-ENOMEM);
+ spin_lock_init(&pll->lock);
+
init.name = name;
init.flags = pll_clk->flags;
init.parent_names = &parent_name;
@@ -551,3 +570,101 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name,
return hw;
}
EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx);
+
+/*
+ * Debugfs interface for Audio PLL runtime monitoring and control
+ *
+ * This interface allows dynamic adjustment of the Audio PLL
+ * K-divider for precise frequency tuning, particularly useful
+ * for audio applications.
+ *
+ * examples for the usage of the two interfaces:
+ * 1): Get the current PLL setting of dividers
+ * cat /sys/kernel/debug/audio_pll_monitor/audio_pll1/pll_parameter
+ *
+ * 2): Adjust the K-divider by a small delta_k
+ * echo 1 > /sys/kernel/debug/audio_pll_monitor/audio_pll1/delta_k;
+ */
+#ifdef CONFIG_DEBUG_FS
+static int pll_delta_k_get(void *data, u64 *val)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(data);
+ *val = pll->delta_k;
+ return 0;
+}
+
+static int pll_delta_k_set(void *data, u64 val)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(data);
+ unsigned long flags;
+ u32 div_ctl1;
+ s16 kdiv, delta_k;
+
+ delta_k = (s16)clamp_t(s64, val, KDIV_MIN, KDIV_MAX);
+
+ spin_lock_irqsave(&pll->lock, flags);
+
+ pll->delta_k = delta_k;
+
+ div_ctl1 = readl_relaxed(pll->base + DIV_CTL1);
+ kdiv = (s16)FIELD_GET(KDIV_MASK, div_ctl1);
+ kdiv = (s16)clamp_t(s32, (s32)kdiv + delta_k, KDIV_MIN, KDIV_MAX);
+ writel_relaxed(FIELD_PREP(KDIV_MASK, kdiv), pll->base + DIV_CTL1);
+
+ spin_unlock_irqrestore(&pll->lock, flags);
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE_SIGNED(delta_k_fops, pll_delta_k_get, pll_delta_k_set, "%lld\n");
+
+static int pll_setting_show(struct seq_file *s, void *data)
+{
+ struct clk_pll14xx *pll = to_clk_pll14xx(s->private);
+ unsigned long flags;
+ u32 div_ctl0, div_ctl1;
+ u32 mdiv, pdiv, sdiv, kdiv;
+
+ spin_lock_irqsave(&pll->lock, flags);
+
+ div_ctl0 = readl_relaxed(pll->base + DIV_CTL0);
+ div_ctl1 = readl_relaxed(pll->base + DIV_CTL1);
+
+ spin_unlock_irqrestore(&pll->lock, flags);
+
+ mdiv = FIELD_GET(MDIV_MASK, div_ctl0);
+ pdiv = FIELD_GET(PDIV_MASK, div_ctl0);
+ sdiv = FIELD_GET(SDIV_MASK, div_ctl0);
+ kdiv = FIELD_GET(KDIV_MASK, div_ctl1);
+
+ seq_printf(s, "Mdiv: 0x%x; Pdiv: 0x%x; Sdiv: 0x%x; Kdiv: 0x%x\n",
+ mdiv, pdiv, sdiv, kdiv);
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(pll_setting);
+
+void imx_audio_pll_debug_init(struct clk_hw *hws[], unsigned int num_plls)
+{
+ struct dentry *rootdir, *audio_pll_dir;
+ const char *pll_name;
+ int i;
+
+ rootdir = debugfs_create_dir("audio_pll_monitor", NULL);
+
+ for (i = 0; i < num_plls; i++) {
+ if (!IS_ERR_OR_NULL(hws[i])) {
+ pll_name = clk_hw_get_name(hws[i]);
+ audio_pll_dir = debugfs_create_dir(pll_name, rootdir);
+ debugfs_create_file_unsafe("delta_k", 0600, audio_pll_dir,
+ hws[i], &delta_k_fops);
+ debugfs_create_file("pll_parameter", 0444, audio_pll_dir,
+ hws[i], &pll_setting_fops);
+ }
+ }
+}
+#else /* !CONFIG_DEBUG_FS */
+void imx_audio_pll_debug_init(struct clk_hw *hws[], unsigned int num_plls)
+{
+}
+#endif /* CONFIG_DEBUG_FS */
+EXPORT_SYMBOL_GPL(imx_audio_pll_debug_init);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index aa5202f284f3d1b7c1b4bf65e2329831832b43a5..40bb41e353f93bf54a6c1b2b6c458f8a65d5845e 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -487,4 +487,5 @@ struct clk_hw *imx_clk_gpr_mux(const char *name, const char *compatible,
u32 reg, const char **parent_names,
u8 num_parents, const u32 *mux_table, u32 mask);
+void imx_audio_pll_debug_init(struct clk_hw *hws[], unsigned int num_plls);
#endif
---
base-commit: a225caacc36546a09586e3ece36c0313146e7da9
change-id: 20260421-imx8m_pll_debugfs-246d0fbbb617
Best regards,
--
Jacky Bai <ping.bai@nxp.com>
^ permalink raw reply related
* Re: [PATCH net-next v6 2/2] net: ti: icssg-prueth: Add ethtool ops for Frame Preemption MAC Merge
From: Meghana Malladi @ 2026-06-04 13:45 UTC (permalink / raw)
To: Maxime Chevallier, liuhangbin, h-mittal1, haokexin,
vadim.fedorenko, devnexen, horms, jacob.e.keller, arnd, afd,
basharath, parvathi, vladimir.oltean, rogerq, danishanwar, pabeni,
kuba, edumazet, davem, andrew+netdev
Cc: linux-arm-kernel, netdev, linux-kernel, srk, Vignesh Raghavendra
In-Reply-To: <7f194a90-8bf6-4217-b5fa-c003b3dc85b3@bootlin.com>
On 5/26/26 01:05, Maxime Chevallier wrote:
> Hi,
>
> On 5/25/26 20:27, Meghana Malladi wrote:
>> From: MD Danish Anwar <danishanwar@ti.com>
>>
>> Add driver support for viewing and changing the MAC Merge sublayer
>> parameters via ethtool ops: .set_mm(), .get_mm() and .get_mm_stats().
>>
>> The minimum size of non-final mPacket fragments supported by the firmware
>> without leading errors is 64 Bytes (including FCS). Verify time
>> bounded to
>> 1-128 ms per 802.3-2018 clause 30.14.1.6. Add a check to ensure
>> user passed tx_min_frag_size argument via ethtool, honors this.
>> Add pa stats registers to check statistics for preemption, which can be
>> dumped using ethtool ops.
>>
>> Fix emac_get_stat_by_name() to return u64 instead of int and return 0 on
>> error instead of -EINVAL. This prevents invalid stat lookups from
>> corrupting
>> output stats with signed error codes cast to u64. Error conditions are
>> still
>> logged via netdev_err().
>>
>> Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
>> Signed-off-by: Meghana Malladi <m-malladi@ti.com>
>> ---
>>
>> v6-v5:
>> - Initialize tx_min_frag_size and verify_time with valid values
>> to avoid returning corrupted values during get_mm()
>> - Fix rx_min_frag_size to ETH_ZLEN excluding ETH_FCS_LEN
>> - Fix return codes for emac_set_mm()
>> All the above changes address the comments raised by sashiko
>>
>> drivers/net/ethernet/ti/icssg/icssg_ethtool.c | 106 ++++++++++++++++++
>> drivers/net/ethernet/ti/icssg/icssg_prueth.h | 7 +-
>> drivers/net/ethernet/ti/icssg/icssg_qos.h | 46 ++++++++
>> drivers/net/ethernet/ti/icssg/icssg_stats.c | 4 +-
>> drivers/net/ethernet/ti/icssg/icssg_stats.h | 7 +-
>> .../net/ethernet/ti/icssg/icssg_switch_map.h | 5 +
>> 6 files changed, 168 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c b/drivers/
>> net/ethernet/ti/icssg/icssg_ethtool.c
>> index b715af21d23ac..ee940051644d6 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_ethtool.c
>> @@ -294,6 +294,109 @@ static int emac_set_per_queue_coalesce(struct
>> net_device *ndev, u32 queue,
>> return 0;
>> }
>> +static int emac_get_mm(struct net_device *ndev, struct
>> ethtool_mm_state *state)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + enum icssg_ietfpe_verify_states verify_status;
>> +
>> + if (emac->is_sr1)
>> + return -EOPNOTSUPP;
>> +
>> + mutex_lock(&iet->fpe_lock);
>> + state->tx_enabled = iet->fpe_enabled;
>> + state->tx_min_frag_size = iet->tx_min_frag_size;
>> + state->tx_active = iet->fpe_active;
>> + state->verify_enabled = iet->mac_verify_configure;
>> + state->verify_time = iet->verify_time_ms;
>> + verify_status = iet->verify_status;
>> + mutex_unlock(&iet->fpe_lock);
>> +
>> + state->rx_min_frag_size = ETH_ZLEN;
>> + state->pmac_enabled = true;
>> +
>> + switch (verify_status) {
>> + case ICSSG_IETFPE_STATE_DISABLED:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_DISABLED;
>> + break;
>> + case ICSSG_IETFPE_STATE_INITIAL:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_INITIAL;
>> + break;
>> + case ICSSG_IETFPE_STATE_VERIFYING:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_VERIFYING;
>> + break;
>> + case ICSSG_IETFPE_STATE_SUCCEEDED:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_SUCCEEDED;
>> + break;
>> + case ICSSG_IETFPE_STATE_FAILED:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_FAILED;
>> + break;
>> + default:
>> + state->verify_status = ETHTOOL_MM_VERIFY_STATUS_UNKNOWN;
>> + break;
>> + }
>> +
>> + /* 802.3-2018 clause 30.14.1.6, says that the aMACMergeVerifyTime
>> + * variable has a range between 1 and 128 ms inclusive. Limit to
>> that.
>> + */
>> + state->max_verify_time = ETHTOOL_MM_MAX_VERIFY_TIME_MS;
>> +
>> + return 0;
>> +}
>> +
>> +static int emac_set_mm(struct net_device *ndev, struct ethtool_mm_cfg
>> *cfg,
>> + struct netlink_ext_ack *extack)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> + struct prueth_qos_iet *iet = &emac->qos.iet;
>> + int err;
>> +
>> + if (emac->is_sr1)
>> + return -EOPNOTSUPP;
>> +
>> + if (!cfg->pmac_enabled) {
>> + NL_SET_ERR_MSG_MOD(extack, "preemptible MAC is always enabled");
>> + return -EOPNOTSUPP;
>> + }
>> +
>> + err = icssg_qos_validate_tx_min_frag_size(cfg->tx_min_frag_size,
>> extack);
>> + if (err)
>> + return err;
>> +
>> + err = icssg_qos_validate_verify_time(cfg->verify_time, extack);
>> + if (err)
>> + return err;
>
> The ethnl code already validates the verify_time :
>
> https://elixir.bootlin.com/linux/v7.0.9/source/net/ethtool/mm.c#L153
>
I remember getting a comment asking me to add a comment or check to
validate tx_min_frag_size, I don't remember at this point why I added
for verify_time as well, lost track in the comments lot. I will remove
it. Just to confirm, do I need icssg_qos_validate_tx_min_frag_size() or
can I remove it as well ?
>> +
>> + mutex_lock(&iet->fpe_lock);
>> + iet->verify_time_ms = cfg->verify_time;
>> + iet->tx_min_frag_size = cfg->tx_min_frag_size;
>> + iet->fpe_enabled = cfg->tx_enabled;
>> + iet->mac_verify_configure = cfg->verify_enabled;
>> + err = icssg_config_ietfpe(ndev, cfg->tx_enabled);
>> + mutex_unlock(&iet->fpe_lock);
>> +
>> + return err;
>> +}
>> +
>> +static void emac_get_mm_stats(struct net_device *ndev,
>> + struct ethtool_mm_stats *s)
>> +{
>> + struct prueth_emac *emac = netdev_priv(ndev);
>> +
>> + if (emac->is_sr1)
>> + return;
>> +
>> + if (!emac->prueth->pa_stats)
>> + return;
>> +
>> + /* MACMergeHoldCount stats is not tracked by the firmware */
>> + s->MACMergeFrameAssOkCount = emac_get_stat_by_name(emac,
>> "FW_PREEMPT_ASSEMBLY_OK");
>> + s->MACMergeFrameAssErrorCount = emac_get_stat_by_name(emac,
>> "FW_PREEMPT_ASSEMBLY_ERR");
>> + s->MACMergeFragCountRx = emac_get_stat_by_name(emac,
>> "FW_PREEMPT_FRAG_CNT_RX");
>> + s->MACMergeFragCountTx = emac_get_stat_by_name(emac,
>> "FW_PREEMPT_FRAG_CNT_TX");
>> + s->MACMergeFrameSmdErrorCount = emac_get_stat_by_name(emac,
>> "FW_PREEMPT_BAD_FRAG");
>> +}
>> +
>> const struct ethtool_ops icssg_ethtool_ops = {
>> .get_drvinfo = emac_get_drvinfo,
>> .get_msglevel = emac_get_msglevel,
>> @@ -317,5 +420,8 @@ const struct ethtool_ops icssg_ethtool_ops = {
>> .set_eee = emac_set_eee,
>> .nway_reset = emac_nway_reset,
>> .get_rmon_stats = emac_get_rmon_stats,
>> + .get_mm = emac_get_mm,
>> + .set_mm = emac_set_mm,
>> + .get_mm_stats = emac_get_mm_stats,
>> };
>> EXPORT_SYMBOL_GPL(icssg_ethtool_ops);
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/
>> net/ethernet/ti/icssg/icssg_prueth.h
>> index 85f7017d2c8e7..61320c252bec2 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
>> @@ -45,6 +45,7 @@
>> #include "icss_iep.h"
>> #include "icssg_switch_map.h"
>> #include "icssg_qos.h"
>> +#include "icssg_stats.h"
>> #define PRUETH_MAX_MTU (2000 - ETH_HLEN - ETH_FCS_LEN)
>> #define PRUETH_MIN_PKT_SIZE (VLAN_ETH_ZLEN)
>> @@ -58,8 +59,8 @@
>> #define ICSSG_MAX_RFLOWS 8 /* per slice */
>> -#define ICSSG_NUM_PA_STATS 32
>> -#define ICSSG_NUM_MIIG_STATS 60
>> +#define ICSSG_NUM_PA_STATS ARRAY_SIZE(icssg_all_pa_stats)
>> +#define ICSSG_NUM_MIIG_STATS ARRAY_SIZE(icssg_all_miig_stats)
>> /* Number of ICSSG related stats */
>> #define ICSSG_NUM_STATS (ICSSG_NUM_MIIG_STATS + ICSSG_NUM_PA_STATS)
>> #define ICSSG_NUM_STANDARD_STATS 31
>> @@ -460,7 +461,7 @@ int emac_fdb_flow_id_updated(struct prueth_emac
>> *emac);
>> void icssg_stats_work_handler(struct work_struct *work);
>> void emac_update_hardware_stats(struct prueth_emac *emac);
>> -int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name);
>> +u64 emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name);
>> /* Common functions */
>> void prueth_cleanup_rx_chns(struct prueth_emac *emac,
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_qos.h b/drivers/net/
>> ethernet/ti/icssg/icssg_qos.h
>> index 9355e96bbcda8..87ca031afcaa4 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_qos.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_qos.h
>> @@ -13,6 +13,7 @@
>> #define ICSSG_EXPRESS_Q_MASK_ALL 0xFF
>> #define ICSSG_IET_MAX_VERIFY_TIME 128
>> #define ICSSG_IET_MIN_VERIFY_TIME 1
>> +#define ICSSG_IET_MAX_TX_MIN_FRAG_SIZE 252
>> /**
>> * enum icssg_ietfpe_verify_states - status of MAC Merge Verify
>> returned by firmware
>> @@ -63,4 +64,49 @@ void icssg_qos_link_state_update(struct net_device
>> *ndev);
>> int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum
>> tc_setup_type type,
>> void *type_data);
>> int icssg_config_ietfpe(struct net_device *ndev, bool enable);
>> +static inline int icssg_qos_validate_tx_min_frag_size(u32 min_frag_size,
>> + struct netlink_ext_ack *extack)
>> +{
>> + /* Firmware takes min_frag_size including FCS length.
>> + * The firmware requires the fragment size (including FCS) to be
>> + * a multiple of 64 bytes. Since 64 bytes = ETH_ZLEN + ETH_FCS_LEN,
>> + * valid user-facing values are: 60, 124, 188, 252.
>> + */
>> +
>> + if (min_frag_size < ETH_ZLEN) {
>> + NL_SET_ERR_MSG_MOD(extack,
>> + "tx_min_frag_size must be at least 60 bytes");
>> + return -EINVAL;
>> + }
>> +
>> + if (min_frag_size > ICSSG_IET_MAX_TX_MIN_FRAG_SIZE) {
>> + NL_SET_ERR_MSG_MOD(extack,
>> + "tx_min_frag_size must not exceed 252 bytes");
>> + return -EINVAL;
>> + }
>> +
>> + if ((min_frag_size + ETH_FCS_LEN) % (ETH_ZLEN + ETH_FCS_LEN)) {
>> + NL_SET_ERR_MSG_MOD(extack,
>> + "tx_min_frag_size must be a multiple of 64 bytes
>> minus 4");
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>
> Is there any reason this helper is in a header file instead
> of being directly in icssg_ethtool.c ?
>
I don't have any strong reason as such, I didn't want to put any helper
functions in icssg_ethtool.c.
>> +
>> +static inline int icssg_qos_validate_verify_time(u32 verify_time_ms,
>> + struct netlink_ext_ack *extack)
>> +{
>> + /* 802.3-2018 clause 30.14.1.6: aMACMergeVerifyTime must be
>> + * between 1 and 128 ms inclusive
>> + */
>> + if (verify_time_ms < ICSSG_IET_MIN_VERIFY_TIME ||
>> + verify_time_ms > ICSSG_IET_MAX_VERIFY_TIME) {
>> + NL_SET_ERR_MSG_MOD(extack,
>> + "verify_time must be between 1 and 128 ms");
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>
> And this shouldn't be needed as the ethnl mm code already validates
> these boundaries, as they are straight from the standard.
>
Will remove this is my next version.
>> #endif /* __NET_TI_ICSSG_QOS_H */
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.c b/drivers/
>> net/ethernet/ti/icssg/icssg_stats.c
>> index 7159baa0155cf..cfdb6f5dc5da1 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_stats.c
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.c
>> @@ -74,7 +74,7 @@ void icssg_stats_work_handler(struct work_struct *work)
>> }
>> EXPORT_SYMBOL_GPL(icssg_stats_work_handler);
>> -int emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name)
>> +u64 emac_get_stat_by_name(struct prueth_emac *emac, char *stat_name)
>> {
>> int i;
>> @@ -91,5 +91,5 @@ int emac_get_stat_by_name(struct prueth_emac *emac,
>> char *stat_name)
>> }
>> netdev_err(emac->ndev, "Invalid stats %s\n", stat_name);
>> - return -EINVAL;
>> + return 0;
>> }
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_stats.h b/drivers/
>> net/ethernet/ti/icssg/icssg_stats.h
>> index 5ec0b38e0c67d..8073deac35c3e 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_stats.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_stats.h
>> @@ -8,8 +8,6 @@
>> #ifndef __NET_TI_ICSSG_STATS_H
>> #define __NET_TI_ICSSG_STATS_H
>> -#include "icssg_prueth.h"
>> -
>> #define STATS_TIME_LIMIT_1G_MS 25000 /* 25 seconds @ 1G */
>> struct miig_stats_regs {
>> @@ -189,6 +187,11 @@ static const struct icssg_pa_stats
>> icssg_all_pa_stats[] = {
>> ICSSG_PA_STATS(FW_INF_DROP_PRIOTAGGED),
>> ICSSG_PA_STATS(FW_INF_DROP_NOTAG),
>> ICSSG_PA_STATS(FW_INF_DROP_NOTMEMBER),
>> + ICSSG_PA_STATS(FW_PREEMPT_BAD_FRAG),
>> + ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_ERR),
>> + ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_TX),
>> + ICSSG_PA_STATS(FW_PREEMPT_ASSEMBLY_OK),
>> + ICSSG_PA_STATS(FW_PREEMPT_FRAG_CNT_RX),
>> ICSSG_PA_STATS(FW_RX_EOF_SHORT_FRMERR),
>> ICSSG_PA_STATS(FW_RX_B0_DROP_EARLY_EOF),
>> ICSSG_PA_STATS(FW_TX_JUMBO_FRM_CUTOFF),
>> diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/
>> drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> index 7e053b8af3ece..855fd4ed0b3f6 100644
>> --- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> +++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h
>> @@ -256,6 +256,11 @@
>> #define FW_INF_DROP_PRIOTAGGED 0x0148
>> #define FW_INF_DROP_NOTAG 0x0150
>> #define FW_INF_DROP_NOTMEMBER 0x0158
>> +#define FW_PREEMPT_BAD_FRAG 0x0160
>> +#define FW_PREEMPT_ASSEMBLY_ERR 0x0168
>> +#define FW_PREEMPT_FRAG_CNT_TX 0x0170
>> +#define FW_PREEMPT_ASSEMBLY_OK 0x0178
>> +#define FW_PREEMPT_FRAG_CNT_RX 0x0180
>> #define FW_RX_EOF_SHORT_FRMERR 0x0188
>> #define FW_RX_B0_DROP_EARLY_EOF 0x0190
>> #define FW_TX_JUMBO_FRM_CUTOFF 0x0198
>
> Maxime
Thanks,
Meghana
^ permalink raw reply
* Re: [PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device
From: Sudeep Holla @ 2026-06-04 13:45 UTC (permalink / raw)
To: Aneesh Kumar K.V
Cc: linux-coco, linux-arm-kernel, linux-kernel, Catalin Marinas,
Sudeep Holla, Greg KH, Jeremy Linton, Jonathan Cameron,
Lorenzo Pieralisi, Mark Rutland, Will Deacon, Steven Price,
Suzuki K Poulose
In-Reply-To: <yq5ase72qvwb.fsf@kernel.org>
On Thu, Jun 04, 2026 at 06:56:28PM +0530, Aneesh Kumar K.V wrote:
> Sudeep Holla <sudeep.holla@kernel.org> writes:
>
> ...
>
> > +static const struct smccc_device_info smccc_devices[] __initconst = {
> > + {
> > + .func_id = ARM_SMCCC_TRNG_VERSION,
> > + .requires_smc = false,
> > + .min_return = ARM_SMCCC_TRNG_MIN_VERSION,
> > + .device_name = "arm-smccc-trng",
> > + },
> > +};
> > +
> > +static bool __init
> > +smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
> > +{
> > + struct arm_smccc_res res;
> > + unsigned long ret;
> > +
> > + if (!IS_ENABLED(CONFIG_ARM64))
> > + return false;
> > +
> > + if (smccc_conduit == SMCCC_CONDUIT_NONE)
> > + return false;
> > +
> > + if (smccc_dev->requires_smc && smccc_conduit != SMCCC_CONDUIT_SMC)
> > + return false;
> > +
> > + arm_smccc_1_1_invoke(smccc_dev->func_id, &res);
> > + ret = res.a0;
> > +
> > + if ((s32)ret < 0)
> > + return false;
> > +
> > + return ret >= smccc_dev->min_return;
> > +}
> > +
> >
>
> I am not sure we want the check to be as simple as ret < 0. Some
> function IDs may return input errors based on the supplied arguments
> (for example, RMI_ERROR_INPUT). In those cases, we would likely want
> this to be handled via a callback.
>
As I mentioned in response to Suzuki, we can defer that to probe of
that device. If *_VERSION, succeeds SMCCC core can add that device and
leave the rest to the core keeping the core and bus layer simple IMO.
> We also want to use conditional compilation for some function IDs.
> Given the callback approach and the #ifdefs, I wonder whether what we
> currently have is actually simpler and more flexible.”
>
I was trying to avoid conditional compilation altogether and hence the
reason for keeping it as simple as possible. Also IS_ENABLED(CONFIG_ARM64)
in above snippet must come as some condition to this generic probe.
Adding any more logic or callback defeats the bus idea here if we need
to rely/depend on multiple conditional compilation or callbacks IMO.
Let's find see if it can work with what we are adding now and may add in
near future and then decide.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v8 2/5] thermal: samsung: Add Exynos ACPM TMU driver GS101
From: Alexey Klimov @ 2026-06-04 13:52 UTC (permalink / raw)
To: Tudor Ambarus, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Bartlomiej Zolnierkiewicz, Krzysztof Kozlowski, Kees Cook,
Gustavo A. R. Silva, Peter Griffin, André Draszik,
Alim Akhtar
Cc: jyescas, linux-kernel, linux-samsung-soc, linux-pm, devicetree,
linux-hardening, linux-arm-kernel, Krzysztof Kozlowski
In-Reply-To: <20260603-acpm-tmu-v8-2-0f1810a356e6@linaro.org>
On Wed Jun 3, 2026 at 2:00 PM BST, Tudor Ambarus wrote:
> Add driver for the Thermal Management Unit (TMU) managed via the Alive
> Clock and Power Manager (ACPM), found on Samsung Exynos SoCs such as
> the Google GS101.
>
> The TMU on the GS101 utilizes a hybrid management model shared between
> the Application Processor (AP) and the ACPM firmware. The driver
> maintains direct memory-mapped access to the TMU interrupt pending
> registers to identify thermal events, while delegating functional
> tasks - such as sensor initialization, threshold configuration, and
> temperature acquisition, to the ACPM firmware via the ACPM IPC
> protocol.
>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@linaro.org>
> Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Alexey Klimov <alexey.klimov@linaro.org>
> ---
> drivers/thermal/samsung/Kconfig | 19 ++
> drivers/thermal/samsung/Makefile | 2 +
> drivers/thermal/samsung/acpm-tmu.c | 651 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 672 insertions(+)
[...]
Best regards,
Alexey
^ permalink raw reply
* [RFC PATCH v3 0/9] accel: rocket: Add RK3568 NPU support
From: Midgy BALON @ 2026-06-04 13:52 UTC (permalink / raw)
To: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will
Cc: robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
RFC, not for merge. End-to-end inference does not produce correct output
yet (see Status), so per the v2 discussion this is a request for design
feedback. It now probes, attaches, and submits cleanly on a stock
v7.1-rc6 tree; what remains is one hardware-internal issue.
The RK3568 has a single NVDLA-derived NPU core, the same IP family as the
RK3588 NPU the driver already supports; the register layout matches. The
RK3568 differences are a 32-bit NPU AXI/IOMMU (vs 40-bit) and explicit
PVTPLL/PMU bring-up to power and de-idle the NPU before it is reachable.
Patches:
1-2 rocket: per-SoC data struct, then derive DMA width and core count
from match data (refactors, no functional change).
3 rocket: RK3568 SoC data + PVTPLL/PMU/NOC bring-up.
4 rocket: reset the NPU before detaching the IOMMU on a job timeout
(the detach otherwise stalls a wedged AXI master and WARNs).
5 rocket: keep the IOMMU domain attached across jobs instead of
re-attaching per job (the per-job rk_iommu handshake on the idle
NPU MMU is slow and noisy).
6 iommu/rockchip: clear AUTO_GATING bit 1 on the RK356x v1 IOMMU so
the page-walker keeps its clock (else a TLB-miss walk never
completes).
7 dt-bindings: add the RK3568 NPU compatible.
8-9 arm64 dts: add the NPU and its IOMMU, and enable them on ROCK 3B.
Dependency. The NPU MMU is rockchip-iommu v1 (32-bit) while the rest of
the RK3568 uses v2 (40-bit). They cannot coexist until the driver carries
per-device ops; this series is developed on top of Simon Xue's
"iommu/rockchip: Drop global rk_ops in favor of per-device ops" [1].
Without it the NPU IOMMU fails to probe on a full RK3568 boot.
Power bring-up. The NPU is brought up through the power-domain layer (no
driver hack): the NPU power-domain keeps its clocks but drops the pm_qos
phandle (qos_npu sits behind the gated NPU NoC, so genpd's power-off QoS
save faults reading it), and vdd_npu is marked always-on so the rail is
up before genpd de-idles the NoC at power-on. The PMU de-idle then ACKs
without PVTPLL running; PVTPLL is only needed for compute.
Status. On v7.1-rc6 the driver probes, creates /dev/accel/accel0,
attaches an IOMMU domain, and submits jobs; the program controller
fetches and broadcasts the command list. Inference output is still wrong,
and the cause is split across three layers:
- kernel (this series): the RK3568 differences appear handled;
- mesa/Teflon userspace: still emits RK3588-tuned config, wrong for
RK3568 (to be filed separately on mesa-dev);
- hardware: with corrected config the NPU's DMA reads the full input
and weight tensors (confirmed via its DMA bandwidth counters), but
the MAC/output stage never completes, the job times out, and the
output stays at the buffer's zero-point. I have not found the missing
step; it is not in the command list (replaying the vendor's
byte-exact command list behaves the same). Pointers welcome,
especially from anyone with RK3568 NPU experience.
Known residual. On the first IOMMU attach the NPU MMU is idle with paging
already enabled; the rk_iommu stall/reset handshake does not complete in
that state and logs one burst of timeouts before the (kept) domain
settles. It is harmless here because the job times out regardless, but it
points at an idle-MMU reconfiguration corner the rk_iommu code does not
handle on this block.
[1] https://lore.kernel.org/linux-rockchip/20260310105303.128859-1-xxm@rock-chips.com/
Changes since v2:
- Tagged RFC; now tested on a stock v7.1-rc6 tree.
- Bring-up moved into the power-domain/DT layer (no initcall hack).
- Added the IOMMU detach-on-timeout and attach-once driver fixes.
- Split the driver patch (Heiko): soc_data / match-data / RK3568.
- Derive DMA width and core count from match data; drop the DT rescans.
- Binding describes the hardware; added the missing $ref on rockchip,pmu.
- Disclosed the per-device-ops IOMMU dependency.
Midgy BALON (9):
accel: rocket: Introduce per-SoC rocket_soc_data
accel: rocket: Derive DMA width and core count from match data
accel: rocket: Add RK3568 SoC support
accel: rocket: Reset the NPU before detaching the IOMMU on timeout
accel: rocket: Keep the IOMMU domain attached across jobs
iommu/rockchip: Clear AUTO_GATING bit 1 on the RK356x v1 IOMMU
dt-bindings: npu: rockchip,rk3588-rknn-core: Add RK3568
arm64: dts: rockchip: rk356x: Add the NPU and its IOMMU
arm64: dts: rockchip: rk3568-rock-3b: Enable the NPU
.../npu/rockchip,rk3588-rknn-core.yaml | 18 ++++-
.../boot/dts/rockchip/rk3568-rock-3b.dts | 14 +++-
arch/arm64/boot/dts/rockchip/rk356x-base.dtsi | 38 +++++++++++
drivers/accel/rocket/rocket_core.c | 22 ++++++-
drivers/accel/rocket/rocket_core.h | 19 ++++++
drivers/accel/rocket/rocket_device.c | 15 ++---
drivers/accel/rocket/rocket_device.h | 3 +-
drivers/accel/rocket/rocket_drv.c | 66 ++++++++++++++++++-
drivers/accel/rocket/rocket_job.c | 35 ++++++++--
drivers/iommu/rockchip-iommu.c | 12 ++++
10 files changed, 219 insertions(+), 23 deletions(-)
base-commit: 52c800fdcf11888ebeb50c3d707f782cc15b66eb
--
2.39.5
^ permalink raw reply
* [RFC PATCH v3 1/9] accel: rocket: Introduce per-SoC rocket_soc_data
From: Midgy BALON @ 2026-06-04 13:52 UTC (permalink / raw)
To: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will
Cc: robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <20260604135255.62682-1-midgy971@gmail.com>
Add a per-SoC data structure carried in the OF match table, currently
holding only the NPU AXI address width, and use it for the per-core DMA
mask instead of a hardcoded 40-bit value. No functional change: the
RK3588 AXI master is 40-bit. This prepares for SoCs with a narrower
address width.
Signed-off-by: Midgy BALON <midgy971@gmail.com>
---
drivers/accel/rocket/rocket_core.c | 7 ++++++-
drivers/accel/rocket/rocket_core.h | 11 +++++++++++
drivers/accel/rocket/rocket_drv.c | 6 +++++-
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/accel/rocket/rocket_core.c b/drivers/accel/rocket/rocket_core.c
index b3b2fa9ba645a..09c445af7de73 100644
--- a/drivers/accel/rocket/rocket_core.c
+++ b/drivers/accel/rocket/rocket_core.c
@@ -7,6 +7,7 @@
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/iommu.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
@@ -21,6 +22,10 @@ int rocket_core_init(struct rocket_core *core)
u32 version;
int err = 0;
+ core->soc_data = of_device_get_match_data(dev);
+ if (!core->soc_data)
+ return dev_err_probe(dev, -EINVAL, "missing SoC match data\n");
+
core->resets[0].id = "srst_a";
core->resets[1].id = "srst_h";
err = devm_reset_control_bulk_get_exclusive(&pdev->dev, ARRAY_SIZE(core->resets),
@@ -52,7 +57,7 @@ int rocket_core_init(struct rocket_core *core)
dma_set_max_seg_size(dev, UINT_MAX);
- err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(core->soc_data->dma_bits));
if (err)
return err;
diff --git a/drivers/accel/rocket/rocket_core.h b/drivers/accel/rocket/rocket_core.h
index f6d7382854ca9..8ee105a0be40e 100644
--- a/drivers/accel/rocket/rocket_core.h
+++ b/drivers/accel/rocket/rocket_core.h
@@ -12,6 +12,16 @@
#include "rocket_registers.h"
+struct rocket_core;
+
+/**
+ * struct rocket_soc_data - per-SoC configuration data
+ * @dma_bits: Physical address width reachable by the NPU's AXI master.
+ */
+struct rocket_soc_data {
+ unsigned int dma_bits;
+};
+
#define rocket_pc_readl(core, reg) \
readl((core)->pc_iomem + (REG_PC_##reg))
#define rocket_pc_writel(core, reg, value) \
@@ -31,6 +41,7 @@ struct rocket_core {
struct device *dev;
struct rocket_device *rdev;
unsigned int index;
+ const struct rocket_soc_data *soc_data;
int irq;
void __iomem *pc_iomem;
diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
index 8bbbce594883e..384c38e13acce 100644
--- a/drivers/accel/rocket/rocket_drv.c
+++ b/drivers/accel/rocket/rocket_drv.c
@@ -213,8 +213,12 @@ static void rocket_remove(struct platform_device *pdev)
}
}
+static const struct rocket_soc_data rk3588_soc_data = {
+ .dma_bits = 40,
+};
+
static const struct of_device_id dt_match[] = {
- { .compatible = "rockchip,rk3588-rknn-core" },
+ { .compatible = "rockchip,rk3588-rknn-core", .data = &rk3588_soc_data },
{}
};
MODULE_DEVICE_TABLE(of, dt_match);
--
2.39.5
^ permalink raw reply related
* [RFC PATCH v3 2/9] accel: rocket: Derive DMA width and core count from match data
From: Midgy BALON @ 2026-06-04 13:52 UTC (permalink / raw)
To: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will
Cc: robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <20260604135255.62682-1-midgy971@gmail.com>
The probe already has the per-SoC match data, which now records the core
count and DMA width. Use it for the cores array allocation and the
device DMA mask instead of re-scanning the device tree for available core
nodes.
Signed-off-by: Midgy BALON <midgy971@gmail.com>
---
drivers/accel/rocket/rocket_core.h | 2 ++
drivers/accel/rocket/rocket_device.c | 15 +++++----------
drivers/accel/rocket/rocket_device.h | 3 ++-
drivers/accel/rocket/rocket_drv.c | 7 ++++++-
4 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/accel/rocket/rocket_core.h b/drivers/accel/rocket/rocket_core.h
index 8ee105a0be40e..d6421251670dc 100644
--- a/drivers/accel/rocket/rocket_core.h
+++ b/drivers/accel/rocket/rocket_core.h
@@ -16,9 +16,11 @@ struct rocket_core;
/**
* struct rocket_soc_data - per-SoC configuration data
+ * @num_cores: Number of NPU cores in this SoC.
* @dma_bits: Physical address width reachable by the NPU's AXI master.
*/
struct rocket_soc_data {
+ unsigned int num_cores;
unsigned int dma_bits;
};
diff --git a/drivers/accel/rocket/rocket_device.c b/drivers/accel/rocket/rocket_device.c
index 46e6ee1e72c5f..6186f4faa3a2a 100644
--- a/drivers/accel/rocket/rocket_device.c
+++ b/drivers/accel/rocket/rocket_device.c
@@ -6,18 +6,16 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
-#include <linux/of.h>
#include "rocket_device.h"
struct rocket_device *rocket_device_init(struct platform_device *pdev,
- const struct drm_driver *rocket_drm_driver)
+ const struct drm_driver *rocket_drm_driver,
+ const struct rocket_soc_data *soc_data)
{
struct device *dev = &pdev->dev;
- struct device_node *core_node;
struct rocket_device *rdev;
struct drm_device *ddev;
- unsigned int num_cores = 0;
int err;
rdev = devm_drm_dev_alloc(dev, rocket_drm_driver, struct rocket_device, ddev);
@@ -27,17 +25,14 @@ struct rocket_device *rocket_device_init(struct platform_device *pdev,
ddev = &rdev->ddev;
dev_set_drvdata(dev, rdev);
- for_each_compatible_node(core_node, NULL, "rockchip,rk3588-rknn-core")
- if (of_device_is_available(core_node))
- num_cores++;
-
- rdev->cores = devm_kcalloc(dev, num_cores, sizeof(*rdev->cores), GFP_KERNEL);
+ rdev->cores = devm_kcalloc(dev, soc_data->num_cores, sizeof(*rdev->cores),
+ GFP_KERNEL);
if (!rdev->cores)
return ERR_PTR(-ENOMEM);
dma_set_max_seg_size(dev, UINT_MAX);
- err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(40));
+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(soc_data->dma_bits));
if (err)
return ERR_PTR(err);
diff --git a/drivers/accel/rocket/rocket_device.h b/drivers/accel/rocket/rocket_device.h
index ce662abc01d3d..2f74e078974e3 100644
--- a/drivers/accel/rocket/rocket_device.h
+++ b/drivers/accel/rocket/rocket_device.h
@@ -22,7 +22,8 @@ struct rocket_device {
};
struct rocket_device *rocket_device_init(struct platform_device *pdev,
- const struct drm_driver *rocket_drm_driver);
+ const struct drm_driver *rocket_drm_driver,
+ const struct rocket_soc_data *soc_data);
void rocket_device_fini(struct rocket_device *rdev);
#define to_rocket_device(drm_dev) \
((struct rocket_device *)(container_of((drm_dev), struct rocket_device, ddev)))
diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
index 384c38e13acce..c18840e5aff76 100644
--- a/drivers/accel/rocket/rocket_drv.c
+++ b/drivers/accel/rocket/rocket_drv.c
@@ -159,11 +159,15 @@ static const struct drm_driver rocket_drm_driver = {
static int rocket_probe(struct platform_device *pdev)
{
+ const struct rocket_soc_data *soc_data = of_device_get_match_data(&pdev->dev);
int ret;
+ if (!soc_data)
+ return -EINVAL;
+
if (rdev == NULL) {
/* First core probing, initialize DRM device. */
- rdev = rocket_device_init(drm_dev, &rocket_drm_driver);
+ rdev = rocket_device_init(drm_dev, &rocket_drm_driver, soc_data);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to initialize rocket device\n");
return PTR_ERR(rdev);
@@ -214,6 +218,7 @@ static void rocket_remove(struct platform_device *pdev)
}
static const struct rocket_soc_data rk3588_soc_data = {
+ .num_cores = 3,
.dma_bits = 40,
};
--
2.39.5
^ permalink raw reply related
* [RFC PATCH v3 5/9] accel: rocket: Keep the IOMMU domain attached across jobs
From: Midgy BALON @ 2026-06-04 13:52 UTC (permalink / raw)
To: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will
Cc: robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <20260604135255.62682-1-midgy971@gmail.com>
rocket attached the job's IOMMU domain in rocket_job_run() and
detached it again on every completion and reset. Each attach/detach
toggles the rk_iommu stall/force-reset/paging handshake, and on
RK3568 the NPU MMU is idle between jobs, so that handshake times out
and logs a burst of "stall/paging request timed out" errors for
every job.
Attach the per-context domain once and keep it: track the attached
domain in the core, swap it only when a job from a different context
runs, and detach it at core teardown. A reference on the attached
domain is held so it outlives the job that first attached it and is
released on swap/teardown.
Signed-off-by: Midgy BALON <midgy971@gmail.com>
---
drivers/accel/rocket/rocket_core.c | 6 ++++++
drivers/accel/rocket/rocket_core.h | 3 +++
drivers/accel/rocket/rocket_job.c | 27 +++++++++++++++++++++------
3 files changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/accel/rocket/rocket_core.c b/drivers/accel/rocket/rocket_core.c
index a8de876365873..634f78dfe2887 100644
--- a/drivers/accel/rocket/rocket_core.c
+++ b/drivers/accel/rocket/rocket_core.c
@@ -13,6 +13,7 @@
#include <linux/reset.h>
#include "rocket_core.h"
+#include "rocket_drv.h"
#include "rocket_job.h"
int rocket_core_init(struct rocket_core *core)
@@ -112,6 +113,11 @@ void rocket_core_fini(struct rocket_core *core)
{
pm_runtime_dont_use_autosuspend(core->dev);
pm_runtime_disable(core->dev);
+ if (core->attached_domain) {
+ iommu_detach_group(NULL, core->iommu_group);
+ rocket_iommu_domain_put(core->attached_domain);
+ core->attached_domain = NULL;
+ }
iommu_group_put(core->iommu_group);
core->iommu_group = NULL;
rocket_job_fini(core);
diff --git a/drivers/accel/rocket/rocket_core.h b/drivers/accel/rocket/rocket_core.h
index 66d138a8ed773..05a197a9c0113 100644
--- a/drivers/accel/rocket/rocket_core.h
+++ b/drivers/accel/rocket/rocket_core.h
@@ -42,6 +42,8 @@ struct rocket_soc_data {
#define rocket_core_writel(core, reg, value) \
writel(value, (core)->core_iomem + (REG_CORE_##reg) - REG_CORE_S_STATUS)
+struct rocket_iommu_domain;
+
struct rocket_core {
struct device *dev;
struct rocket_device *rdev;
@@ -56,6 +58,7 @@ struct rocket_core {
struct reset_control_bulk_data resets[2];
struct iommu_group *iommu_group;
+ struct rocket_iommu_domain *attached_domain;
struct mutex job_lock;
struct rocket_job *in_flight_job;
diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
index e25234261536b..b248371be8a1e 100644
--- a/drivers/accel/rocket/rocket_job.c
+++ b/drivers/accel/rocket/rocket_job.c
@@ -9,6 +9,7 @@
#include <drm/rocket_accel.h>
#include <linux/interrupt.h>
#include <linux/iommu.h>
+#include <linux/kref.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -314,9 +315,26 @@ static struct dma_fence *rocket_job_run(struct drm_sched_job *sched_job)
if (ret < 0)
return fence;
- ret = iommu_attach_group(job->domain->domain, core->iommu_group);
- if (ret < 0)
- return fence;
+ /*
+ * Attach the job's IOMMU domain only when it differs from the one
+ * already attached. Re-attaching per job toggles the rk_iommu
+ * stall/reset handshake on an idle NPU MMU, which is slow and
+ * noisy; keep the domain attached across jobs instead.
+ */
+ if (core->attached_domain != job->domain) {
+ if (core->attached_domain) {
+ iommu_detach_group(NULL, core->iommu_group);
+ rocket_iommu_domain_put(core->attached_domain);
+ core->attached_domain = NULL;
+ }
+
+ ret = iommu_attach_group(job->domain->domain, core->iommu_group);
+ if (ret < 0)
+ return fence;
+
+ kref_get(&job->domain->kref);
+ core->attached_domain = job->domain;
+ }
scoped_guard(mutex, &core->job_lock) {
core->in_flight_job = job;
@@ -340,7 +358,6 @@ static void rocket_job_handle_irq(struct rocket_core *core)
return;
}
- iommu_detach_group(NULL, iommu_group_get(core->dev));
dma_fence_signal(core->in_flight_job->done_fence);
pm_runtime_put_autosuspend(core->dev);
core->in_flight_job = NULL;
@@ -376,8 +393,6 @@ rocket_reset(struct rocket_core *core, struct drm_sched_job *bad)
*/
rocket_core_reset(core);
- iommu_detach_group(NULL, core->iommu_group);
-
/* NPU has been reset, we can clear the reset pending bit. */
atomic_set(&core->reset.pending, 0);
--
2.39.5
^ permalink raw reply related
* [RFC PATCH v3 4/9] accel: rocket: Reset the NPU before detaching the IOMMU on timeout
From: Midgy BALON @ 2026-06-04 13:52 UTC (permalink / raw)
To: tomeu, ogabbay, heiko, robh, krzk+dt, conor+dt, joro, will
Cc: robin.murphy, dri-devel, linux-rockchip, devicetree,
linux-arm-kernel, iommu, linux-kernel
In-Reply-To: <20260604135255.62682-1-midgy971@gmail.com>
On a job timeout the NPU AXI master can be left wedged with
outstanding transactions. rocket_reset() detached the IOMMU group
before resetting the hardware, so iommu_detach_group() ->
__iommu_group_set_core_domain() asked the rk_iommu to stall and wait
for the in-flight transactions to drain. They never did, the stall
request timed out (-ETIMEDOUT) and the IOMMU core WARNed:
WARNING: drivers/iommu/iommu.c:157 __iommu_group_set_core_domain
iommu_detach_group
rocket_reset
rocket_job_timedout
Assert the core reset first: it quiesces the AXI master so the
following IOMMU detach completes cleanly. Move the detach after
rocket_core_reset() and out of the job_lock (it does not touch
in_flight_job).
Signed-off-by: Midgy BALON <midgy971@gmail.com>
---
drivers/accel/rocket/rocket_job.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
index ac51bff39833f..e25234261536b 100644
--- a/drivers/accel/rocket/rocket_job.c
+++ b/drivers/accel/rocket/rocket_job.c
@@ -364,14 +364,20 @@ rocket_reset(struct rocket_core *core, struct drm_sched_job *bad)
if (core->in_flight_job)
pm_runtime_put_noidle(core->dev);
- iommu_detach_group(NULL, core->iommu_group);
-
core->in_flight_job = NULL;
}
- /* Proceed with reset now. */
+ /*
+ * Reset the NPU hardware before detaching the IOMMU. A timed-out job
+ * leaves the NPU AXI master wedged; detaching the IOMMU then issues a
+ * stall request that never drains and times out (warning in the IOMMU
+ * core). Asserting the core reset first quiesces the master so the
+ * detach completes cleanly.
+ */
rocket_core_reset(core);
+ iommu_detach_group(NULL, core->iommu_group);
+
/* NPU has been reset, we can clear the reset pending bit. */
atomic_set(&core->reset.pending, 0);
--
2.39.5
^ permalink raw reply related
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