On Thu, Jun 11, 2026 at 04:23:40PM +0530, Gaurav Kohli wrote:
>
>
> On 6/9/2026 5:00 PM, Dmitry Baryshkov wrote:
> > On Tue, Jun 09, 2026 at 03:52:57PM +0530, Gaurav Kohli wrote:
> > > From: Casey Connolly <[email protected]>
> > >
> > > Add a Qualcomm QMI Thermal Mitigation Device (TMD) to support thermal
> > > cooling devices backed by remote subsystems.
> > >
> > > On several Qualcomm platforms, remote processors (for example modem and
> > > CDSP) expose thermal mitigation controls through the TMD QMI service.
> > > Client drivers need a way to discover that service, map DT thermal
> > > mitigation endpoints to cooling devices, and forward cooling state
> > > updates to the remote subsystem.
> > >
> > > Co-developed-by: Gaurav Kohli <[email protected]>
> > > Signed-off-by: Gaurav Kohli <[email protected]>
> > > Signed-off-by: Casey Connolly <[email protected]>
> > > Signed-off-by: Daniel Lezcano <[email protected]>
> >
> > Wrong SoB chain.
> >
>
> Thanks for review, Ack.
>
> > > ---
> > > MAINTAINERS | 6 +
> > > drivers/soc/qcom/Kconfig | 10 +
> > > drivers/soc/qcom/Makefile | 1 +
> > > drivers/soc/qcom/qmi_tmd.c | 604
> > > +++++++++++++++++++++++++++++++++++++++
> > > include/linux/soc/qcom/qmi.h | 1 +
> > > include/linux/soc/qcom/qmi_tmd.h | 23 ++
> > > 6 files changed, 645 insertions(+)
> > >
> > > diff --git a/MAINTAINERS b/MAINTAINERS
> > > index 57656ec0e9d5..3d60702a655a 100644
> > > --- a/MAINTAINERS
> > > +++ b/MAINTAINERS
> > > @@ -22286,6 +22286,12 @@ F:
> > > Documentation/devicetree/bindings/net/qcom,ipq9574-ppe.yaml
> > > F:
> > > Documentation/networking/device_drivers/ethernet/qualcomm/ppe/ppe.rst
> > > F: drivers/net/ethernet/qualcomm/ppe/
> > > +QUALCOMM QMI (REMOTEPROC THERMAL MITIGATION) TMD
> > > +M: Gaurav Kohli <[email protected]>
> > > +L: [email protected]
> > > +L: [email protected]
> > > +F: drivers/soc/qcom/qmi_tmd.c
> > > +
> > > QUALCOMM QSEECOM DRIVER
> > > M: Maximilian Luz <[email protected]>
> > > L: [email protected]
> > > diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
> > > index 2caadbbcf830..a292ce57fd4a 100644
> > > --- a/drivers/soc/qcom/Kconfig
> > > +++ b/drivers/soc/qcom/Kconfig
> > > @@ -128,6 +128,16 @@ config QCOM_QMI_HELPERS
> > > tristate
> > > depends on NET
> > > +config QCOM_QMI_TMD
> > > + bool "Qualcomm QMI TMD library" if COMPILE_TEST
> > > + depends on ARCH_QCOM
> > > + select QCOM_QMI_HELPERS
> > > + help
> > > + This enables the QMI-based Thermal Mitigation Device (TMD) library
> > > + for Qualcomm remote subsystems. The library manages TMD messaging and
> > > + handles QMI communication with remote processors (modem, CDSP) to
> > > + exchange mitigation state and apply thermal mitigation requests.
> > > +
> > > config QCOM_RAMP_CTRL
> > > tristate "Qualcomm Ramp Controller driver"
> > > depends on ARCH_QCOM || COMPILE_TEST
> > > diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
> > > index b7f1d2a57367..4544e61c74e7 100644
> > > --- a/drivers/soc/qcom/Makefile
> > > +++ b/drivers/soc/qcom/Makefile
> > > @@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink.o
> > > obj-$(CONFIG_QCOM_PMIC_GLINK) += pmic_glink_altmode.o
> > > obj-$(CONFIG_QCOM_PMIC_PDCHARGER_ULOG) += pmic_pdcharger_ulog.o
> > > CFLAGS_pmic_pdcharger_ulog.o := -I$(src)
> > > +obj-$(CONFIG_QCOM_QMI_TMD) += qmi_tmd.o
> > > obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
> > > qmi_helpers-y += qmi_encdec.o qmi_interface.o
> > > obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
> > > diff --git a/drivers/soc/qcom/qmi_tmd.c b/drivers/soc/qcom/qmi_tmd.c
> > > new file mode 100644
> > > index 000000000000..9d88ae48c864
> > > --- /dev/null
> > > +++ b/drivers/soc/qcom/qmi_tmd.c
> > > @@ -0,0 +1,604 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * Copyright (c) 2025, Linaro Limited
> > > + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> > > + *
> > > + * QMI Thermal Mitigation Device (TMD) library.
> > > + * This library provides cooling device support for remote subsystems
> > > + * (modem and CDSP) running the TMD service via QMI.
> >
> > Why are you limiting it to these DSPs only? I quickly checked, my X13s
> > (sc8280xp) also has one on the ADSP.
> >
>
> Adsp is low power dsp, not prone to thermal issues and no TMD service is up
> and running. So we are defining for Cdsp and Modem only.
Again, if there is no TMD service, what do I observe on my laptop? Or
what do I see on other devices (checked on SM8350, which I had at hand)?
# qrtr-lookup |grep Thermal.mitigation
24 1 0 0 22 Thermal mitigation device service
24 1 1 5 9 Thermal mitigation device service
24 1 67 10 9 Thermal mitigation device service
# echo stop > /sys/class/remoteproc/
# cat /sys/class/remoteproc/remoteproc*/name
adsp
modem
slpi
cdsp
# echo stop > /sys/class/remoteproc/remoteproc0/state
[ 68.353571] ucsi_glink.pmic_glink_ucsi pmic_glink.ucsi.0: failed to send
UCSI write request: -5
[ 68.354150] qcom_q6v5_pas 3000000.remoteproc: Handover signaled, but it
already happened
[ 68.503057] remoteproc remoteproc0: stopped remote processor adsp
# qrtr-lookup | grep Thermal.mitigation
24 1 0 0 22 Thermal mitigation device service
24 1 67 10 9 Thermal mitigation device service
So, obviously, there is a TMD service running on the ADSP.
> > > +
> > > +static int qmi_tmd_get_cur_state(struct thermal_cooling_device *cdev,
> > > + unsigned long *state)
> > > +{
> > > + struct qmi_tmd *tmd = cdev->devdata;
> > > +
> > > + *state = tmd->cur_state;
> >
> > Mutex protection?
> >
>
> This callback only reads the cached local state and does not perform any QMI
> transaction, that's why not using lock here.
And what is protecting the cached state from the concurrent
modification, ending up with the read of incorrect value?
>
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int qmi_tmd_set_cur_state(struct thermal_cooling_device *cdev,
> > > + unsigned long state)
> > > +{
> > > + struct qmi_tmd *tmd = cdev->devdata;
> > > + int ret;
> > > +
> > > + if (state > tmd->max_state)
> > > + return -EINVAL;
> > > +
> > > + if (tmd->cur_state == state)
> > > + return 0;
> >
> > Hmm, again, mutex protection for the cur_state? Or is it provided by the
> > thermal core?
> >
>
> Yes, it is already protected by cdev->lock.
Comment.
>
> > > +
> > > + ret = qmi_tmd_send_state_request(tmd, state);
> > > + if (!ret)
> > > + tmd->cur_state = state;
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static const struct thermal_cooling_device_ops qmi_tmd_cooling_ops = {
> > > + .get_max_state = qmi_tmd_get_max_state,
> > > + .get_cur_state = qmi_tmd_get_cur_state,
> > > + .set_cur_state = qmi_tmd_set_cur_state,
> > > +};
> > > +
> > > +static int qmi_tmd_register(struct qmi_tmd_client *qmi_tmd_cli,
> > > + const char *label, u8 max_state)
> > > +{
> > > + struct device *dev = qmi_tmd_cli->dev;
> > > + struct qmi_tmd *tmd;
> > > + int index;
> > > +
> > > + for (index = 0; index < qmi_tmd_cli->num_tmds; index++) {
> > > + tmd = &qmi_tmd_cli->tmds[index];
> > > +
> > > + if (!strncasecmp(tmd->name, label,
> > > + QMI_TMD_DEV_ID_LEN_MAX + 1))
> > > + goto found;
> > > + }
> > > +
> > > + dev_dbg(qmi_tmd_cli->dev,
> > > + "TMD '%s' available in firmware but not specified in DT\n",
> > > + label);
> >
> > If we can read them from the firmware, why do you need to specify them
> > in DT?
> >
>
> We need DT, because cooling-device binding is index-based as per new thermal
> framework changes:
> https://lore.kernel.org/all/[email protected]/
>
> And also the firmware list is name-based and ordering is not consistent
> across platforms/firmware. DT provides the explicit set and order of TMDs
> that thermal framework should bind. Firmware may also expose
> additional/virtual TMD's that are not used for binding with thermal zone.
I've asked this elsewhere. It's not clear how different TMDs are used.
There are comments by other reviewers regarding the tmd-names property.
--
With best wishes
Dmitry