Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Re: [PATCH] ASoC: imx-rpmsg: Fix ignore-suspend-widgets only applied to codec DAPM
From: Mark Brown @ 2026-04-14 13:57 UTC (permalink / raw)
  To: Chancel Liu
  Cc: shengjiu.wang@gmail.com, Xiubo.Lee@gmail.com, festevam@gmail.com,
	nicoleotsuka@gmail.com, lgirdwood@gmail.com, perex@perex.cz,
	tiwai@suse.com, Frank Li, s.hauer@pengutronix.de,
	kernel@pengutronix.de, linux-sound@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org
In-Reply-To: <AM9PR04MB83539BD1328151697DA85859E3242@AM9PR04MB8353.eurprd04.prod.outlook.com>

[-- Attachment #1: Type: text/plain, Size: 1427 bytes --]

On Mon, Apr 13, 2026 at 03:13:51AM +0000, Chancel Liu wrote:

> Thanks for pointing this out. I really appreciate your suggestion to
> move this functionality into core-level. Several machine drivers could
> benefit if there's an unified ignore‑suspend mechanism.

> I have an idea to make it support a generic and reusable mechanism in
> the core rather than something each machine driver has to re‑implement.
> The design follows a simple structure:

> 1. Parse and store the name of widgets to ignore suspend in 
> struct snd_soc_card

> The name list of widgets to ignore suspend can come either from DT or
> from the machine driver. Different boards/machines have different
> routing and power requirements. So allowing DT to specify
> "ignore-suspend-widgets" is important. It enables each device to define
> its own policy rather than forcing hard‑coded rules. To support this, a
> helper such as snd_soc_of_parse_ignore_suspend_widgets() can be defined
> in core and provided.

> 2. Apply ignore_suspend flags during snd_soc_bind_card()

> After all components have been probed and all DAPM widgets are
> registered in snd_soc_bind_card(), perform a unified search through
> the card’s widget list and mark matching widgets with
> ignore_suspend = 1. Any runtime prefixing applied during widget
> creation should be handled well by the lookup.

That sounds like a reasonable plan.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: [PATCH v2] Bluetooth: Add Broadcom channel priority commands
From: Luiz Augusto von Dentz @ 2026-04-14 14:00 UTC (permalink / raw)
  To: fnkl.kernel
  Cc: Sven Peter, Janne Grunau, Neal Gompa, Marcel Holtmann,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, linux-kernel, asahi, linux-arm-kernel,
	linux-bluetooth, netdev
In-Reply-To: <20260407-brcm-prio-v2-1-3f745edf49af@gmail.com>

Hi Sasha,

On Tue, Apr 7, 2026 at 1:46 PM Sasha Finkelstein via B4 Relay
<devnull+fnkl.kernel.gmail.com@kernel.org> wrote:
>
> From: Sasha Finkelstein <fnkl.kernel@gmail.com>
>
> Certain Broadcom bluetooth chips (bcm4377/bcm4378/bcm438) need ACL
> streams carrying audio to be set as "high priority" using a vendor
> specific command to prevent 10-ish second-long dropouts whenever
> something does a device scan. This patch sends the command when the
> socket priority is set to TC_PRIO_INTERACTIVE, as BlueZ does for audio.
>
> Signed-off-by: Sasha Finkelstein <fnkl.kernel@gmail.com>
> ---
> Changes in v2:
> - new ioctl got nack-ed, so let's use sk_priority as the trigger
> - Link to v1: https://lore.kernel.org/r/20260407-brcm-prio-v1-1-f38b17376640@gmail.com
> ---
>  MAINTAINERS                       |  2 ++
>  drivers/bluetooth/hci_bcm4377.c   |  2 ++
>  include/net/bluetooth/bluetooth.h |  4 ++++
>  include/net/bluetooth/hci_core.h  | 11 +++++++++++
>  net/bluetooth/Kconfig             |  7 +++++++
>  net/bluetooth/Makefile            |  1 +
>  net/bluetooth/brcm.c              | 29 +++++++++++++++++++++++++++++
>  net/bluetooth/brcm.h              | 17 +++++++++++++++++
>  net/bluetooth/hci_conn.c          | 28 ++++++++++++++++++++++++++++
>  net/bluetooth/l2cap_sock.c        | 13 +++++++++++++
>  10 files changed, 114 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c3fe46d7c4bc..81be021367ec 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2562,6 +2562,8 @@ F:        include/dt-bindings/pinctrl/apple.h
>  F:     include/linux/mfd/macsmc.h
>  F:     include/linux/soc/apple/*
>  F:     include/uapi/drm/asahi_drm.h
> +F:     net/bluetooth/brcm.c
> +F:     net/bluetooth/brcm.h
>
>  ARM/ARTPEC MACHINE SUPPORT
>  M:     Jesper Nilsson <jesper.nilsson@axis.com>
> diff --git a/drivers/bluetooth/hci_bcm4377.c b/drivers/bluetooth/hci_bcm4377.c
> index 925d0a635945..5f79920c0306 100644
> --- a/drivers/bluetooth/hci_bcm4377.c
> +++ b/drivers/bluetooth/hci_bcm4377.c
> @@ -2397,6 +2397,8 @@ static int bcm4377_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>         if (bcm4377->hw->broken_le_ext_adv_report_phy)
>                 hci_set_quirk(hdev, HCI_QUIRK_FIXUP_LE_EXT_ADV_REPORT_PHY);
>
> +       hci_set_brcm_capable(hdev);
> +
>         pci_set_drvdata(pdev, bcm4377);
>         hci_set_drvdata(hdev, bcm4377);
>         SET_HCIDEV_DEV(hdev, &pdev->dev);
> diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
> index 69eed69f7f26..07a250673950 100644
> --- a/include/net/bluetooth/bluetooth.h
> +++ b/include/net/bluetooth/bluetooth.h
> @@ -457,6 +457,7 @@ struct l2cap_ctrl {
>  };
>
>  struct hci_dev;
> +struct hci_conn;
>
>  typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
>  typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status,
> @@ -469,6 +470,9 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
>  int hci_ethtool_ts_info(unsigned int index, int sk_proto,
>                         struct kernel_ethtool_ts_info *ts_info);
>
> +int hci_conn_setsockopt(struct hci_conn *conn, struct sock *sk, int level,
> +                       int optname, sockptr_t optval, unsigned int optlen);
> +
>  #define HCI_REQ_START  BIT(0)
>  #define HCI_REQ_SKB    BIT(1)
>
> diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
> index a7bffb908c1e..947e7c2b08dd 100644
> --- a/include/net/bluetooth/hci_core.h
> +++ b/include/net/bluetooth/hci_core.h
> @@ -642,6 +642,10 @@ struct hci_dev {
>         bool                    aosp_quality_report;
>  #endif
>
> +#if IS_ENABLED(CONFIG_BT_BRCMEXT)
> +       bool                    brcm_capable;
> +#endif
> +
>         int (*open)(struct hci_dev *hdev);
>         int (*close)(struct hci_dev *hdev);
>         int (*flush)(struct hci_dev *hdev);
> @@ -1791,6 +1795,13 @@ static inline void hci_set_aosp_capable(struct hci_dev *hdev)
>  #endif
>  }
>
> +static inline void hci_set_brcm_capable(struct hci_dev *hdev)
> +{
> +#if IS_ENABLED(CONFIG_BT_BRCMEXT)
> +       hdev->brcm_capable = true;
> +#endif
> +}
> +
>  static inline void hci_devcd_setup(struct hci_dev *hdev)
>  {
>  #ifdef CONFIG_DEV_COREDUMP
> diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
> index 6b2b65a66700..0f2a5fbcafc5 100644
> --- a/net/bluetooth/Kconfig
> +++ b/net/bluetooth/Kconfig
> @@ -110,6 +110,13 @@ config BT_AOSPEXT
>           This options enables support for the Android Open Source
>           Project defined HCI vendor extensions.
>
> +config BT_BRCMEXT
> +       bool "Enable Broadcom extensions"
> +       depends on BT
> +       help
> +         This option enables support for the Broadcom defined HCI
> +         vendor extensions.
> +
>  config BT_DEBUGFS
>         bool "Export Bluetooth internals in debugfs"
>         depends on BT && DEBUG_FS
> diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
> index a7eede7616d8..b4c9013a46ce 100644
> --- a/net/bluetooth/Makefile
> +++ b/net/bluetooth/Makefile
> @@ -24,5 +24,6 @@ bluetooth-$(CONFIG_BT_LE) += iso.o
>  bluetooth-$(CONFIG_BT_LEDS) += leds.o
>  bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
>  bluetooth-$(CONFIG_BT_AOSPEXT) += aosp.o
> +bluetooth-$(CONFIG_BT_BRCMEXT) += brcm.o
>  bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o
>  bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o
> diff --git a/net/bluetooth/brcm.c b/net/bluetooth/brcm.c
> new file mode 100644
> index 000000000000..9aa0a265ab3d
> --- /dev/null
> +++ b/net/bluetooth/brcm.c
> @@ -0,0 +1,29 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 The Asahi Linux Contributors
> + */
> +
> +#include <net/bluetooth/bluetooth.h>
> +#include <net/bluetooth/hci_core.h>
> +
> +#include "brcm.h"
> +
> +int brcm_set_high_priority(struct hci_dev *hdev, u16 handle, bool enable)
> +{
> +       struct sk_buff *skb;
> +       u8 cmd[3];
> +
> +       if (!hdev->brcm_capable)
> +               return 0;
> +
> +       cmd[0] = handle;
> +       cmd[1] = handle >> 8;

Adding a packed struct and then using something like cpu_to_le16 is
probably preferable over above.

> +       cmd[2] = !!enable;
> +
> +       skb = hci_cmd_sync(hdev, 0xfc57, sizeof(cmd), cmd, HCI_CMD_TIMEOUT);
> +       if (IS_ERR(skb))
> +               return PTR_ERR(skb);
> +
> +       kfree_skb(skb);
> +       return 0;
> +}
> diff --git a/net/bluetooth/brcm.h b/net/bluetooth/brcm.h
> new file mode 100644
> index 000000000000..fdaee63bd1d2
> --- /dev/null
> +++ b/net/bluetooth/brcm.h
> @@ -0,0 +1,17 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2026 The Asahi Linux Contributors
> + */
> +
> +#if IS_ENABLED(CONFIG_BT_BRCMEXT)
> +
> +int brcm_set_high_priority(struct hci_dev *hdev, u16 handle, bool enable);
> +
> +#else
> +
> +static inline int brcm_set_high_priority(struct hci_dev *hdev, u16 handle, bool enable)
> +{
> +       return 0;
> +}
> +
> +#endif
> diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
> index 11d3ad8d2551..096163840f62 100644
> --- a/net/bluetooth/hci_conn.c
> +++ b/net/bluetooth/hci_conn.c
> @@ -35,6 +35,7 @@
>  #include <net/bluetooth/iso.h>
>  #include <net/bluetooth/mgmt.h>
>
> +#include "brcm.h"
>  #include "smp.h"
>  #include "eir.h"
>
> @@ -3070,6 +3071,33 @@ int hci_conn_set_phy(struct hci_conn *conn, u32 phys)
>         }
>  }
>
> +int hci_conn_setsockopt(struct hci_conn *conn, struct sock *sk, int level,
> +                       int optname, sockptr_t optval, unsigned int optlen)
> +{
> +       int val;
> +       bool old_high, new_high, changed;
> +
> +       if (level != SOL_SOCKET)
> +               return 0;
> +
> +       if (optname != SO_PRIORITY)
> +               return 0;
> +
> +       if (optlen < sizeof(int))
> +               return -EINVAL;
> +
> +       if (copy_from_sockptr(&val, optval, sizeof(val)))
> +               return -EFAULT;
> +
> +       old_high = sk->sk_priority >= TC_PRIO_INTERACTIVE;
> +       new_high = val >= TC_PRIO_INTERACTIVE;
> +       changed = old_high != new_high;
> +       if (!changed)
> +               return 0;
> +
> +       return brcm_set_high_priority(conn->hdev, conn->handle, new_high);

The skb carries the priority (skb->priority), not sure why you need to
capture the sk_priority instead, doing so ignores the load balance
that hci_core performs to avoid starving connections.

> +}
> +
>  static int abort_conn_sync(struct hci_dev *hdev, void *data)
>  {
>         struct hci_conn *conn = data;
> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> index 71e8c1b45bce..d5eef87accc4 100644
> --- a/net/bluetooth/l2cap_sock.c
> +++ b/net/bluetooth/l2cap_sock.c
> @@ -891,6 +891,16 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
>
>         BT_DBG("sk %p", sk);
>
> +       if (level == SOL_SOCKET) {
> +               conn = chan->conn;
> +               if (conn)
> +                       err = hci_conn_setsockopt(conn->hcon, sock->sk, level,
> +                                                 optname, optval, optlen);
> +               if (err)
> +                       return err;
> +               return sock_setsockopt(sock, level, optname, optval, optlen);
> +       }
> +
>         if (level == SOL_L2CAP)
>                 return l2cap_sock_setsockopt_old(sock, optname, optval, optlen);
>
> @@ -1931,6 +1941,9 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
>
>         INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
>
> +       if (sock)
> +               set_bit(SOCK_CUSTOM_SOCKOPT, &sock->flags);

This is more complicated than it needs to be. I'd just add a new
callback, `hdev->set_priority(handle, skb->priority)`, so the driver
is called whenever it needs to elevate a connection's priority, that
said there could be cases where a connection needs its priority set
momentarily to transmit A2DP, followed by OBEX packets that are best
effort. Therefore, `hci_conn` will probably need to track the priority
so it can detect when it needs changing on a per skb basis.

>         chan = l2cap_chan_create();
>         if (!chan) {
>                 sk_free(sk);
>
> ---
> base-commit: bfe62a454542cfad3379f6ef5680b125f41e20f4
> change-id: 20260407-brcm-prio-b630e6cc3834
>
> Best regards,
> --
> Sasha Finkelstein <fnkl.kernel@gmail.com>
>
>


-- 
Luiz Augusto von Dentz


^ permalink raw reply

* Re: [PATCH v2 2/3] pmdomain: core: add support for power-domains-child-ids
From: Ulf Hansson @ 2026-04-14 14:03 UTC (permalink / raw)
  To: Kevin Hilman (TI)
  Cc: Rob Herring, Geert Uytterhoeven, linux-pm, devicetree,
	linux-kernel, arm-scmi, linux-arm-kernel
In-Reply-To: <20260410-topic-lpm-pmdomain-child-ids-v2-2-83396e4b5f8b@baylibre.com>

On Sat, 11 Apr 2026 at 01:44, Kevin Hilman (TI) <khilman@baylibre.com> wrote:
>
> Currently, PM domains can only support hierarchy for simple
> providers (e.g. ones with #power-domain-cells = 0).
>
> Add support for oncell providers as well by adding a new property
> `power-domains-child-ids` to describe the parent/child relationship.
>
> For example, an SCMI PM domain provider has multiple domains, each of
> which might be a child of diffeent parent domains. In this example,
> the parent domains are MAIN_PD and WKUP_PD:
>
>     scmi_pds: protocol@11 {
>         reg = <0x11>;
>         #power-domain-cells = <1>;
>         power-domains = <&MAIN_PD>, <&WKUP_PD>;
>         power-domains-child-ids = <15>, <19>;
>     };
>
> With this example using the new property, SCMI PM domain 15 becomes a
> child domain of MAIN_PD, and SCMI domain 19 becomes a child domain of
> WKUP_PD.
>
> To support this feature, add two new core functions
>
> - of_genpd_add_child_ids()
> - of_genpd_remove_child_ids()
>
> which can be called by pmdomain providers to add/remove child domains
> if they support the new property power-domains-child-ids.
>
> The add function is "all or nothing".  If it cannot add all of the
> child domains in the list, it will unwind any additions already made
> and report a failure.
>
> Signed-off-by: Kevin Hilman (TI) <khilman@baylibre.com>
> ---
>  drivers/pmdomain/core.c   | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/pm_domain.h |  16 ++++++++++++++++
>  2 files changed, 182 insertions(+)
>
> diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
> index 61c2277c9ce3..f978477dd546 100644
> --- a/drivers/pmdomain/core.c
> +++ b/drivers/pmdomain/core.c
> @@ -2909,6 +2909,172 @@ static struct generic_pm_domain *genpd_get_from_provider(
>         return genpd;
>  }
>
> +/**
> + * of_genpd_add_child_ids() - Parse power-domains-child-ids property
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Parse the power-domains and power-domains-child-ids properties to establish
> + * parent-child relationships for PM domains. The power-domains property lists
> + * parent domains, and power-domains-child-ids lists which child domain IDs
> + * should be associated with each parent.
> + *
> + * Uses "all or nothing" semantics: either all relationships are established
> + * successfully, or none are (any partially-added relationships are unwound
> + * on error).
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error code.
> + */

As I mentioned in my earlier reply for the previous version, returning
a specific error code when the property doesn't exist will complicate
handling for the caller. Moreover, we also need to make sure we don't
returning the same error code (-ENOENT) for a different error further
down the execution path in of_genpd_add_child_ids(). Otherwise it
would the caller treat the error code in the wrong way.

To me, there are two better ways to address this. For both options,
of_genpd_add_child_ids() should return 0 when
"power-domains-child-ids" is missing.

1) Add another helper function that checks if
"power-domains-child-ids" exists. The caller can then use this to
pre-parse the property and decide whether to treat it as an error.

2) As I suggested earlier, let of_genpd_add_child_ids() return the
number of assigned parents/children, while still using the all or
nothing approach, of course.

Kind regards
Uffe

> +int of_genpd_add_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data)
> +{
> +       struct of_phandle_args parent_args;
> +       struct generic_pm_domain *parent_genpd, *child_genpd;
> +       struct generic_pm_domain **pairs; /* pairs[2*i]=parent, pairs[2*i+1]=child */
> +       u32 child_id;
> +       int i, ret, count, child_count, added = 0;
> +
> +       /* Check if both properties exist */
> +       count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
> +       if (count <= 0)
> +               return -ENOENT;
> +
> +       child_count = of_property_count_u32_elems(np, "power-domains-child-ids");
> +       if (child_count < 0)
> +               return -ENOENT;
> +       if (child_count != count)
> +               return -EINVAL;
> +
> +       /* Allocate tracking array for error unwind (parent/child pairs) */
> +       pairs = kmalloc_array(count * 2, sizeof(*pairs), GFP_KERNEL);
> +       if (!pairs)
> +               return -ENOMEM;
> +
> +       for (i = 0; i < count; i++) {
> +               ret = of_property_read_u32_index(np, "power-domains-child-ids",
> +                                                i, &child_id);
> +               if (ret)
> +                       goto err_unwind;
> +
> +               /* Validate child ID is within bounds */
> +               if (child_id >= data->num_domains) {
> +                       pr_err("Child ID %u out of bounds (max %u) for %pOF\n",
> +                              child_id, data->num_domains - 1, np);
> +                       ret = -EINVAL;
> +                       goto err_unwind;
> +               }
> +
> +               /* Get the child domain */
> +               child_genpd = data->domains[child_id];
> +               if (!child_genpd) {
> +                       pr_err("Child domain %u is NULL for %pOF\n", child_id, np);
> +                       ret = -EINVAL;
> +                       goto err_unwind;
> +               }
> +
> +               ret = of_parse_phandle_with_args(np, "power-domains",
> +                                                "#power-domain-cells", i,
> +                                                &parent_args);
> +               if (ret)
> +                       goto err_unwind;
> +
> +               /* Get the parent domain */
> +               parent_genpd = genpd_get_from_provider(&parent_args);
> +               of_node_put(parent_args.np);
> +               if (IS_ERR(parent_genpd)) {
> +                       pr_err("Failed to get parent domain for %pOF: %ld\n",
> +                              np, PTR_ERR(parent_genpd));
> +                       ret = PTR_ERR(parent_genpd);
> +                       goto err_unwind;
> +               }
> +
> +               /* Establish parent-child relationship */
> +               ret = pm_genpd_add_subdomain(parent_genpd, child_genpd);
> +               if (ret) {
> +                       pr_err("Failed to add child domain %u to parent in %pOF: %d\n",
> +                              child_id, np, ret);
> +                       goto err_unwind;
> +               }
> +
> +               /* Track for potential unwind */
> +               pairs[2 * added] = parent_genpd;
> +               pairs[2 * added + 1] = child_genpd;
> +               added++;
> +
> +               pr_debug("Added child domain %u (%s) to parent %s for %pOF\n",
> +                        child_id, child_genpd->name, parent_genpd->name, np);
> +       }
> +
> +       kfree(pairs);
> +       return 0;
> +
> +err_unwind:
> +       /* Reverse all previously established relationships */
> +       while (added-- > 0)
> +               pm_genpd_remove_subdomain(pairs[2 * added], pairs[2 * added + 1]);
> +       kfree(pairs);
> +       return ret;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_add_child_ids);
> +
> +/**
> + * of_genpd_remove_child_ids() - Remove parent-child PM domain relationships
> + * @np: Device node pointer associated with the PM domain provider.
> + * @data: Pointer to the onecell data associated with the PM domain provider.
> + *
> + * Reverses the effect of of_genpd_add_child_ids() by parsing the same
> + * power-domains and power-domains-child-ids properties and calling
> + * pm_genpd_remove_subdomain() for each established relationship.
> + *
> + * Returns 0 on success, -ENOENT if properties don't exist, or negative error
> + * code on failure.
> + */
> +int of_genpd_remove_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data)
> +{
> +       struct of_phandle_args parent_args;
> +       struct generic_pm_domain *parent_genpd, *child_genpd;
> +       u32 child_id;
> +       int i, ret, count, child_count;
> +
> +       /* Check if both properties exist */
> +       count = of_count_phandle_with_args(np, "power-domains", "#power-domain-cells");
> +       if (count <= 0)
> +               return -ENOENT;
> +
> +       child_count = of_property_count_u32_elems(np, "power-domains-child-ids");
> +       if (child_count < 0)
> +               return -ENOENT;
> +       if (child_count != count)
> +               return -EINVAL;
> +
> +       for (i = 0; i < count; i++) {
> +               if (of_property_read_u32_index(np, "power-domains-child-ids",
> +                                              i, &child_id))
> +                       continue;
> +
> +               if (child_id >= data->num_domains || !data->domains[child_id])
> +                       continue;
> +
> +               ret = of_parse_phandle_with_args(np, "power-domains",
> +                                                "#power-domain-cells", i,
> +                                                &parent_args);
> +               if (ret)
> +                       continue;
> +
> +               parent_genpd = genpd_get_from_provider(&parent_args);
> +               of_node_put(parent_args.np);
> +               if (IS_ERR(parent_genpd))
> +                       continue;
> +
> +               child_genpd = data->domains[child_id];
> +               pm_genpd_remove_subdomain(parent_genpd, child_genpd);
> +       }
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(of_genpd_remove_child_ids);
> +
>  /**
>   * of_genpd_add_device() - Add a device to an I/O PM domain
>   * @genpdspec: OF phandle args to use for look-up PM domain
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index f67a2cb7d781..b44615d79af6 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -465,6 +465,10 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
>  int of_genpd_parse_idle_states(struct device_node *dn,
>                                struct genpd_power_state **states, int *n);
>  void of_genpd_sync_state(struct device_node *np);
> +int of_genpd_add_child_ids(struct device_node *np,
> +                          struct genpd_onecell_data *data);
> +int of_genpd_remove_child_ids(struct device_node *np,
> +                             struct genpd_onecell_data *data);
>
>  int genpd_dev_pm_attach(struct device *dev);
>  struct device *genpd_dev_pm_attach_by_id(struct device *dev,
> @@ -534,6 +538,18 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
>  {
>         return ERR_PTR(-EOPNOTSUPP);
>  }
> +
> +static inline int of_genpd_add_child_ids(struct device_node *np,
> +                                        struct genpd_onecell_data *data)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +static inline int of_genpd_remove_child_ids(struct device_node *np,
> +                                           struct genpd_onecell_data *data)
> +{
> +       return -EOPNOTSUPP;
> +}
>  #endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
>
>  #ifdef CONFIG_PM
>
> --
> 2.51.0
>


^ permalink raw reply

* Re: [PATCH 2/3] gpio: axiado: add SGPIO controller support
From: Krzysztof Kozlowski @ 2026-04-14 14:04 UTC (permalink / raw)
  To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
	Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
  Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-2-b5c7e4c2e69b@axiado.com>

On 14/04/2026 15:48, Petar Stepanovic wrote:
> +
> +	for (i = 0; i < sgpio->max_offset_regs; i++) {
> +		sgpio->slices[2].reg_ss[i] = 0;
> +		dout_value = be32_to_cpu(prop[i]);
> +
> +		for (dout_reverse = 0; dout_reverse < 32; ++dout_reverse) {
> +			sgpio->slices[2].reg_ss[i] <<= 1;
> +			sgpio->slices[2].reg_ss[i] |= (dout_value & 1);
> +			dout_value >>= 1;
> +		}
> +	}
> +
> +	sgpio_hw_init(sgpio);
> +
> +	irq = platform_get_irq(pdev, 0);
> +

Odd style

> +	if (irq < 0) {
> +		dev_err(&pdev->dev, "Failed to get parent IRQ: %d\n", irq);
> +		return irq;
> +	}
> +	/* Store parent IRQ for cleanup */
> +	sgpio->parent_irq = irq;
> +
> +	rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, sgpio_irq_handler,
> +				       IRQF_ONESHOT, "axiado-sgpio", sgpio);
> +
> +	if (rc < 0) {
> +		dev_err(&pdev->dev, "Failed to request threaded IRQ %d: %d\n",
> +			irq, rc);

Nope

> +		return rc;
> +	}
> +
> +	sgpio->chip.parent = &pdev->dev;
> +	sgpio->chip.ngpio = sgpio->ngpios * 2;
> +	sgpio->chip.owner = THIS_MODULE;
> +	sgpio->chip.direction_input = ax3000_sgpio_dir_in;
> +	sgpio->chip.direction_output = ax3000_sgpio_dir_out;
> +	sgpio->chip.get = ax3000_sgpio_get;
> +	sgpio->chip.set = ax3000_sgpio_set;
> +	sgpio->chip.label = dev_name(&pdev->dev);
> +	sgpio->chip.base = -1;
> +
> +	girq = &sgpio->chip.irq;
> +
> +	girq->chip = &axiado_sgpio_irqchip;
> +	girq->handler = handle_edge_irq;
> +	girq->default_type = IRQ_TYPE_NONE;
> +	girq->num_parents = 1;
> +	girq->parents =
> +		devm_kcalloc(&pdev->dev, 1, sizeof(*girq->parents), GFP_KERNEL);
> +	if (!girq->parents) {
> +		dev_err(&pdev->dev, "Failed to allocate parents array\n");
> +		return -ENOMEM;

Ykes...

> +	}



> +
> +static struct platform_driver sgpio_driver = {
> +	.driver = {
> +		.name = "sgpio",
> +		.owner = THIS_MODULE,

Uh, that's 13 year old code. Please drop everything and write from
scratch using latest reviewed drivers as your base. No point to repeat
same review and fix the same issues we already fixed during last 13 years...

> +		.of_match_table = ax_sgpio_match,
> +	},
> +	.probe = sgpio_probe,
> +	.remove = sgpio_remove,
> +};
> +
> +static int __init ax_sgpio_init(void)
> +{
> +	int ret;
> +
> +	ret = platform_driver_register(&sgpio_driver);
> +	if (ret < 0) {
> +		pr_err("Failed to register SGPIO driver\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static void __exit ax_sgpio_exit(void)
> +{
> +	platform_driver_unregister(&sgpio_driver);
> +}
> +
> +module_init(ax_sgpio_init);
> +module_exit(ax_sgpio_exit);

And that's one more.

module_platform_driver, no?

> +
> +MODULE_DESCRIPTION("Axiado Serial GPIO Driver");
> +MODULE_AUTHOR("Axiado Corporation");
> +MODULE_LICENSE("GPL");
> 


Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH 1/3] dt-bindings: gpio: add Axiado SGPIO controller
From: Krzysztof Kozlowski @ 2026-04-14 14:06 UTC (permalink / raw)
  To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
	Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
  Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-1-b5c7e4c2e69b@axiado.com>

On 14/04/2026 15:48, Petar Stepanovic wrote:
> +properties:
> +  compatible:
> +    enum:
> +      - axiado,sgpio

That's a SoC no? Where is SoC compatible?

> +
> +  reg:
> +    maxItems: 1
> +
> +  gpio-controller: true
> +
> +  '#gpio-cells':
> +    const: 2
> +
> +  interrupts:
> +    maxItems: 1
> +
> +  interrupt-controller: true
> +
> +  '#interrupt-cells':
> +    const: 2
> +
> +  design-variant:

Sorry, but no, none of this and further properties apply to DT. Drop all
of them.

Please also read writing bindings so you won't make trivial mistakes.

...


> +    sgpio@a000 {
> +            compatible = "axiado,sgpio";

Don't come with own style, please. Look at other files.

> +            reg = <0xa000 0x800>;
> +            gpio-controller;
> +            #gpio-cells = <2>;
Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v6 3/3] arm64: dts: rockchip: Add Orange Pi 5 Pro board support
From: Dennis Gilmore @ 2026-04-14 14:07 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
	FUKAUMI Naoki, Hsun Lai, Jonas Karlman, Chaoyi Chen, John Clark,
	Michael Opdenacker, Quentin Schulz, Andrew Lunn, Chukun Pan,
	Peter Robinson, Michael Riesch, Mykola Kvach, Jimmy Hon,
	devicetree, linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <CABjd4YwZJe8fO+kJiXRTq5gZirVvKvCqWzNdYqN3-6eMAZUFxQ@mail.gmail.com>

On Sat, Apr 11, 2026 at 1:00 PM Alexey Charkov <alchark@gmail.com> wrote:
>
> On Sat, Apr 11, 2026 at 6:47 AM <dennis@ausil.us> wrote:
> >
> > From: Dennis Gilmore <dennis@ausil.us>
> >
> > Add device tree for the Xunlong Orange Pi 5 Pro (RK3588S).
> >
> > - eMMC module, you can optionally solder a SPI NOR in place and turn
> >  off the eMMC
> > - PCIe-attached NIC (pcie2x1l1)
> > - PCIe NVMe slot (pcie2x1l2)
> > - AP6256 WiFi (BCM43456) via SDIO with mmc-pwrseq
> > - BCM4345C5 Bluetooth
> > - es8388 audio
> > - USB 2.0 and USB 3.0
> > - Two HDMI ports, the second is connected to the SoC's DP controller
> >   driven by a transparent LT8711UXD bridge that has firmware onboard and
> >   needs no node defined.
> >
> > Vendors description and links to schematics available:
> > http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-5-Pro.html
>
> Hi Dennis,
>
> The most useful of these is the schematic, so it's best to include a
> direct link to that in a dedicated Link: tag
>
> Link: https://drive.google.com/file/d/1qs1DratHuh7C6J6MEtQIwUsiSrg8qgTi/view

Will change to that, I did not do it because a random Google Drive
link doesn't really indicate it as a source of truth

> [schematic]
>
> > Signed-off-by: Dennis Gilmore <dennis@ausil.us>
> > ---
> >  .../display/rockchip/rockchip,dw-dp.yaml      |   7 +
> >  arch/arm64/boot/dts/rockchip/Makefile         |   1 +
> >  .../dts/rockchip/rk3588s-orangepi-5-pro.dts   | 352 ++++++++++++++++++
> >  drivers/gpu/drm/bridge/synopsys/dw-dp.c       |  12 +
>
> These should be three separate patches, never lumped together. First
> the binding change, next the driver change. They go together via the
> subsystem tree (likely DRM in this case). Then the DTS addition (or
> change) separately (it goes via the SoC tree).

They were something I was doing as I worked on getting the second HDMI
port working, they ended up not being needed, and I should have
removed it there really should have only been the dts and Makefile. I
should have waited until the morning to review again and send.

> >  4 files changed, 372 insertions(+)
> >  create mode 100644 arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> >
> > diff --git a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > index 6345f0132d43..079a912d97f1 100644
> > --- a/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > +++ b/Documentation/devicetree/bindings/display/rockchip/rockchip,dw-dp.yaml
> > @@ -57,6 +57,13 @@ properties:
> >        - const: i2s
> >        - const: spdif
> >
> > +  hpd-gpios:
> > +    maxItems: 1
> > +    description:
> > +      GPIO used for hot plug detection when the controller's native HPD
> > +      input is not connected. If not specified, the controller uses its
> > +      internal HPD detection mechanism.
>
> Do you actually need this change? According to the schematic, the
> DP_HPDIN line from the DP-HDMI bridge is routed to the native
> DP0_HPDIN_M0 pin of the DP controller, so it shouldn't require this
> GPIO trick if the pinctrl is configured properly.

No I do not, It was an approach I had experimented with but did not
use and did not mean to include here.


> >    phys:
> >      maxItems: 1
> >
> > diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
> > index 4d384f153c13..c99dca2ae9e7 100644
> > --- a/arch/arm64/boot/dts/rockchip/Makefile
> > +++ b/arch/arm64/boot/dts/rockchip/Makefile
> > @@ -214,6 +214,7 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-nanopi-r6c.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-odroid-m2.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5b.dtb
> > +dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-5-pro.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-orangepi-cm5-base.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-radxa-cm5-io.dtb
> >  dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3588s-roc-pc.dtb
> > diff --git a/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > new file mode 100644
> > index 000000000000..84c83aa69f63
> > --- /dev/null
> > +++ b/arch/arm64/boot/dts/rockchip/rk3588s-orangepi-5-pro.dts
> > @@ -0,0 +1,352 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
> > +
> > +/dts-v1/;
> > +
> > +#include "rk3588s-orangepi-5.dtsi"
> > +
> > +/ {
> > +       model = "Xunlong Orange Pi 5 Pro";
> > +       compatible = "xunlong,orangepi-5-pro", "rockchip,rk3588s";
> > +
> > +       aliases {
> > +               mmc0 = &sdhci;
> > +               mmc1 = &sdmmc;
> > +               mmc2 = &sdio;
> > +       };
> > +
> > +       dp-con {
> > +               compatible = "dp-connector";
>
> You don't have a physical DP connector on the board, so this node
> doesn't describe actual hardware, and is thus a no-go. What you have
> instead is an HDMI type A connector routed via an onboard DP to HDMI
> bridge, so you should describe exactly that in the device tree (a node
> for the HDMI connector, a node for the bridge, a node for the DP
> controller, and endpoints connected from the controller to the bridge,
> from the bridge to the connector). Please refer to the device tree for
> Radxa Rock 5 ITX, which has a similar setup (but a different bridge
> IC).
>
> I don't think your LT8711UXD has existing binding or driver entry, so
> a one-line patch will likely be needed to
> Documentation/devicetree/bindings/display/bridge/simple-bridge.yaml,
> and a separate one to drivers/gpu/drm/bridge/simple-bridge.c. Separate
> ones :)

Will add in v7

> > +               port {
> > +                       dp_con_in: endpoint {
> > +                               remote-endpoint = <&dp0_out_con>;
> > +                       };
> > +               };
> > +       };
> > +
> > +       analog-sound {
> > +               compatible = "simple-audio-card";
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&hp_detect>;
> > +               simple-audio-card,bitclock-master = <&masterdai>;
> > +               simple-audio-card,format = "i2s";
> > +               simple-audio-card,frame-master = <&masterdai>;
> > +               simple-audio-card,hp-det-gpios = <&gpio1 RK_PD5 GPIO_ACTIVE_HIGH>;
> > +               simple-audio-card,mclk-fs = <256>;
> > +               simple-audio-card,name = "rockchip,es8388";
> > +               simple-audio-card,routing =
> > +                       "Headphones", "LOUT1",
> > +                       "Headphones", "ROUT1",
> > +                       "LINPUT1", "Microphone Jack",
> > +                       "RINPUT1", "Microphone Jack",
> > +                       "LINPUT2", "Onboard Microphone",
> > +                       "RINPUT2", "Onboard Microphone";
> > +               simple-audio-card,widgets =
> > +                       "Microphone", "Microphone Jack",
> > +                       "Microphone", "Onboard Microphone",
> > +                       "Headphone", "Headphones";
> > +
> > +               simple-audio-card,cpu {
> > +                       sound-dai = <&i2s2_2ch>;
> > +               };
> > +
> > +               masterdai: simple-audio-card,codec {
> > +                       sound-dai = <&es8388>;
> > +                       system-clock-frequency = <12288000>;
> > +               };
> > +       };
> > +
> > +       pwm-leds {
> > +               compatible = "pwm-leds";
> > +
> > +               led-0 {
> > +                       color = <LED_COLOR_ID_BLUE>;
> > +                       function = LED_FUNCTION_STATUS;
> > +                       linux,default-trigger = "heartbeat";
> > +                       max-brightness = <255>;
> > +                       pwms = <&pwm15 0 1000000 0>;
> > +               };
> > +
> > +               led-1 {
> > +                       color = <LED_COLOR_ID_GREEN>;
> > +                       function = LED_FUNCTION_ACTIVITY;
> > +                       linux,default-trigger = "heartbeat";
> > +                       max-brightness = <255>;
> > +                       pwms = <&pwm3 0 1000000 0>;
> > +               };
> > +       };
> > +
> > +       fan: pwm-fan {
> > +               compatible = "pwm-fan";
> > +               #cooling-cells = <2>;
> > +               cooling-levels = <0 50 100 150 200 255>;
> > +               fan-supply = <&vcc5v0_sys>;
> > +               pwms = <&pwm2 0 20000000 0>;
> > +       };
> > +
> > +       vcc3v3_dp: regulator-vcc3v3-dp {
> > +               compatible = "regulator-fixed";
> > +               enable-active-high;
> > +               gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_HIGH>;
>
> Please don't forget to add explicit pinctrl nodes for each GPIO pin
> you use (here and in other places like this). These GPIOs happen to
> work on Linux without configuring their pin control first, but that is
> pure luck and coincidence due to how the respective Linux subsystems
> are wired together, and if you ever need to use this device tree in
> e.g. U-boot (which also derives its DTS from the Linux kernel tree) it
> will break there.

Will do

> > +               regulator-always-on;
> > +               regulator-boot-on;
>
> Does it have to be always-on, boot-on? This looks like a hack to work
> around the fact that you didn't define the bridge node, which uses
> this as its supply. Please model the dependencies explicitly - most
> likely that will let you drop these attributes.

without these the the dp to HDMI bridge does not power up, and HPD
does not work,

> > +               regulator-max-microvolt = <3300000>;
> > +               regulator-min-microvolt = <3300000>;
>
> It's two separate regulators on your schematic, one DCDC at 1.25V and
> the other a load switch at 3.3V, driving six separate voltage inputs
> of the DP bridge. They are both controlled by the same GPIO pin
> though, so _maybe_ it's okay to have just one "virtual" node like this
> to model them together. Would be great for the DT maintainers to weigh
> in on this.
>
> > +               regulator-name = "vcc3v3_dp";
> > +               vin-supply = <&vcc_3v3_s3>;
> > +       };
> > +
> > +       vcc3v3_phy1: regulator-vcc3v3-phy1 {
> > +               compatible = "regulator-fixed";
> > +               enable-active-high;
> > +               gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_HIGH>;
> > +               regulator-boot-on;
>
> See above
>
> > +               regulator-max-microvolt = <3300000>;
> > +               regulator-min-microvolt = <3300000>;
> > +               regulator-name = "vcc3v3_phy1";
> > +               startup-delay-us = <50000>;
> > +               vin-supply = <&vcc_3v3_s3>;
> > +       };
> > +
> > +       vcc5v0_otg: regulator-vcc5v0-otg {
> > +               compatible = "regulator-fixed";
> > +               enable-active-high;
> > +               gpios = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&vcc5v0_otg_en>;
> > +               regulator-max-microvolt = <5000000>;
> > +               regulator-min-microvolt = <5000000>;
> > +               regulator-name = "vcc5v0_otg";
> > +               vin-supply = <&vcc5v0_sys>;
> > +       };
> > +
> > +       sdio_pwrseq: sdio-pwrseq {
> > +               compatible = "mmc-pwrseq-simple";
> > +               clocks = <&hym8563>;
> > +               clock-names = "ext_clock";
> > +               post-power-on-delay-ms = <200>;
> > +               reset-gpios = <&gpio0 RK_PD0 GPIO_ACTIVE_LOW>;
>
> This GPIO also needs a pinctrl
>
> > +       };
> > +
> > +       typea_con: usb-a-connector {
> > +               compatible = "usb-a-connector";
> > +               data-role = "host";
> > +               label = "USB3 Type-A";
> > +               power-role = "source";
> > +               vbus-supply = <&vcc5v0_otg>;
> > +       };
> > +};
> > +
> > +&dp0 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&dp0m0_pins>;
>
> This switches your HPD pin to the native DP controller handling
> (DP0_HPDIN_M0), so the GPIO bits you've patched into the controller
> driver aren't even used, and it doesn't look like you tested that code
> path.

Right, I had not meant to include. It was something I had worked on in
refactoring it and went a different route.

>
> > +       status = "okay";
> > +};
> > +
> > +&dp0_in {
> > +       dp0_in_vp1: endpoint {
> > +               remote-endpoint = <&vp1_out_dp0>;
> > +       };
> > +};
> > +
> > +&dp0_out {
> > +       dp0_out_con: endpoint {
> > +               remote-endpoint = <&dp_con_in>;
>
> This will need to be rewritten once you add the proper bridge chain
> leading up to the HDMI type A connector.

Yep

> > +       };
> > +};
> > +
> > +&i2c1 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&i2c1m4_xfer>;
> > +       status = "okay";
> > +};
> > +
> > +&i2c3 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&i2c3m0_xfer>;
> > +       status = "okay";
> > +
> > +       es8388: audio-codec@11 {
> > +               compatible = "everest,es8388", "everest,es8328";
> > +               reg = <0x11>;
> > +               #sound-dai-cells = <0>;
> > +               AVDD-supply = <&vcc_3v3_s0>;
>
> Are you sure? Schematic says VCCA_3V3_S0, which is a different
> regulator (PLDO4 output of the PMIC)
>
> > +               DVDD-supply = <&vcc_1v8_s0>;
>
> Schematic says VCCA_1V8_S0, which is a different regulator (PLDO1
> output of the PMIC)
>
> > +               HPVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_3V3_S0
>
> > +               PVDD-supply = <&vcc_3v3_s0>;
>
> Schematic says VCCA_1V8_S0

I will rename these. It was what was used in the original orange pi 5
boards and was carried over, but looking at their schematics, they are
labeled the same so changing makes sense. after digging in the Pi 5
Pro names two of the regulators differently to the 5 and 5b. and the
naming of the current ones does not match the schematic

>
> > +               assigned-clock-rates = <12288000>;
> > +               assigned-clocks = <&cru I2S2_2CH_MCLKOUT>;
> > +               clocks = <&cru I2S2_2CH_MCLKOUT>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&i2s2m1_mclk>;
> > +       };
> > +};
> > +
> > +&i2c4 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&i2c4m3_xfer>;
> > +       status = "okay";
> > +};
> > +
> > +&i2s2_2ch {
> > +       pinctrl-0 = <&i2s2m1_lrck &i2s2m1_sclk
> > +                    &i2s2m1_sdi &i2s2m1_sdo>;
> > +       status = "okay";
> > +};
> > +
> > +&package_thermal {
> > +       polling-delay = <1000>;
> > +
> > +       cooling-maps {
> > +               map0 {
> > +                       trip = <&package_fan0>;
> > +                       cooling-device = <&fan THERMAL_NO_LIMIT 1>;
> > +               };
> > +
> > +               map1 {
> > +                       trip = <&package_fan1>;
> > +                       cooling-device = <&fan 2 THERMAL_NO_LIMIT>;
> > +               };
> > +       };
> > +
> > +       trips {
> > +               package_fan0: package-fan0 {
> > +                       hysteresis = <2000>;
> > +                       temperature = <55000>;
> > +                       type = "active";
> > +               };
> > +
> > +               package_fan1: package-fan1 {
> > +                       hysteresis = <2000>;
> > +                       temperature = <65000>;
> > +                       type = "active";
> > +               };
> > +       };
> > +};
> > +
> > +/* NVMe */
> > +&pcie2x1l1 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&pcie30x1m1_1_clkreqn &pcie30x1m1_1_waken>;
> > +       reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix

> > +       supports-clkreq;
> > +       vpcie3v3-supply = <&vcc_3v3_s3>;
> > +       status = "okay";
> > +};
> > +
> > +/* NIC */
> > +&pcie2x1l2 {
> > +       reset-gpios = <&gpio3 RK_PD1 GPIO_ACTIVE_HIGH>;
>
> The GPIO also needs a pinctrl
Will fix

> > +       vpcie3v3-supply = <&vcc3v3_phy1>;
> > +       status = "okay";
> > +};
> > +
> > +&pinctrl {
> > +       bluetooth {
> > +               bt_wake_gpio: bt-wake-pin {
> > +                       rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
> > +               };
> > +
> > +               bt_wake_host_irq: bt-wake-host-irq {
> > +                       rockchip,pins = <0 RK_PC5 RK_FUNC_GPIO &pcfg_pull_down>;
> > +               };
> > +       };
> > +
> > +       usb {
> > +               vcc5v0_otg_en: vcc5v0-otg-en {
> > +                       rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
> > +               };
> > +       };
> > +
> > +       wlan {
> > +               wifi_host_wake_irq: wifi-host-wake-irq {
> > +                       rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_down>;
> > +               };
> > +       };
> > +};
> > +
> > +&pwm15 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&pwm15m2_pins>;
> > +       status = "okay";
> > +};
> > +
> > +&pwm2 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&pwm2m1_pins>;
> > +       status = "okay";
> > +};
> > +
> > +&pwm3 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&pwm3m2_pins>;
> > +       status = "okay";
> > +};
> > +
> > +&sdhci {
> > +       status = "okay";
> > +};
> > +
> > +&sdio {
> > +       #address-cells = <1>;
> > +       #size-cells = <0>;
> > +       bus-width = <4>;
> > +       cap-sd-highspeed;
> > +       cap-sdio-irq;
> > +       keep-power-in-suspend;
> > +       max-frequency = <150000000>;
> > +       mmc-pwrseq = <&sdio_pwrseq>;
> > +       no-mmc;
> > +       no-sd;
> > +       non-removable;
> > +       sd-uhs-sdr104;
> > +       status = "okay";
> > +
> > +       ap6256: wifi@1 {
> > +               compatible = "brcm,bcm43456-fmac", "brcm,bcm4329-fmac";
> > +               reg = <1>;
> > +               interrupt-names = "host-wake";
> > +               interrupt-parent = <&gpio0>;
> > +               interrupts = <RK_PA0 IRQ_TYPE_LEVEL_HIGH>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&wifi_host_wake_irq>;
> > +       };
> > +};
> > +
> > +&uart9 {
> > +       pinctrl-names = "default";
> > +       pinctrl-0 = <&uart9m2_xfer &uart9m2_ctsn &uart9m2_rtsn>;
> > +       uart-has-rtscts;
> > +       status = "okay";
> > +
> > +       bluetooth {
> > +               compatible = "brcm,bcm4345c5";
> > +               clocks = <&hym8563>;
> > +               clock-names = "lpo";
> > +               device-wakeup-gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
> > +               interrupt-names = "host-wakeup";
> > +               interrupt-parent = <&gpio0>;
> > +               interrupts = <RK_PC5 IRQ_TYPE_LEVEL_HIGH>;
> > +               max-speed = <1500000>;
> > +               pinctrl-names = "default";
> > +               pinctrl-0 = <&bt_wake_host_irq &bt_wake_gpio>;
> > +               shutdown-gpios = <&gpio0 RK_PD5 GPIO_ACTIVE_HIGH>;
> > +               vbat-supply = <&vcc_3v3_s3>;
> > +               vddio-supply = <&vcc_1v8_s3>;
> > +       };
> > +};
> > +
> > +&usb_host0_xhci {
> > +       dr_mode = "host";
> > +};
> > +
> > +&usbdp_phy0 {
> > +       rockchip,dp-lane-mux = <0 1>;
>
> I'm wondering if the DP controller's "out" endpoint should go to the
> PHY instead of directly to the connector/bridge. That would describe
> the hardware better.

This was initially added to make sure that the type A port worked
because it uses lanes 2/3, and I needed to make sure 0/1, which route
to the dp were allocated. The DP PHY is already tied to the controller
via the phys property on &dp0 (inherited from rk3588s.dtsi), and the
lane mux is set via rockchip,dp-lane-mux on &usbdp_phy0. This matches
the convention used by rk3588-evb2-v10, rk3588s-coolpi-4b, and
rk3588s-indiedroid-nova — routing the dp0_out endpoint through the PHY
would diverge from the existing binding and all in-tree users.

> > +};
> > +
> > +&vp1 {
> > +       vp1_out_dp0: endpoint@a {
> > +               reg = <ROCKCHIP_VOP2_EP_DP0>;
> > +               remote-endpoint = <&dp0_in_vp1>;
> > +       };
> > +};
> > diff --git a/drivers/gpu/drm/bridge/synopsys/dw-dp.c b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > index fd23ca2834b0..b58f57b69b22 100644
> > --- a/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > +++ b/drivers/gpu/drm/bridge/synopsys/dw-dp.c
> > @@ -8,6 +8,7 @@
> >   */
> >  #include <linux/bitfield.h>
> >  #include <linux/clk.h>
> > +#include <linux/gpio/consumer.h>
> >  #include <linux/iopoll.h>
> >  #include <linux/irq.h>
> >  #include <linux/media-bus-format.h>
> > @@ -330,6 +331,8 @@ struct dw_dp {
> >         u8 pixel_mode;
> >
> >         DECLARE_BITMAP(sdp_reg_bank, SDP_REG_BANK_SIZE);
> > +
> > +       struct gpio_desc *hpd_gpiod;
> >  };
> >
> >  enum {
> > @@ -481,6 +484,9 @@ static bool dw_dp_hpd_detect(struct dw_dp *dp)
> >  {
> >         u32 value;
> >
> > +       if (dp->hpd_gpiod)
> > +               return gpiod_get_value_cansleep(dp->hpd_gpiod);
> > +
> >         regmap_read(dp->regmap, DW_DP_HPD_STATUS, &value);
> >
> >         return FIELD_GET(HPD_STATE, value) == DW_DP_HPD_STATE_PLUG;
> > @@ -2002,6 +2008,12 @@ struct dw_dp *dw_dp_bind(struct device *dev, struct drm_encoder *encoder,
> >                 return ERR_CAST(dp->regmap);
> >         }
> >
> > +       dp->hpd_gpiod = devm_gpiod_get_optional(dev, "hpd", GPIOD_IN);
>
> Not tested, not needed, why bother?..

this is not needed

> Best regards,
> Alexey

Thanks for the feedback


Dennis


^ permalink raw reply

* [PATCH net v2] net: airoha: Wait for NPU PPE configuration to complete in airoha_ppe_offload_setup()
From: Lorenzo Bianconi @ 2026-04-14 14:08 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Lorenzo Bianconi
  Cc: linux-arm-kernel, linux-mediatek, netdev

In order to properly enable flowtable hw offloading, poll
REG_PPE_FLOW_CFG register in airoha_ppe_offload_setup routine and
wait for NPU PPE configuration triggered by ppe_init callback to complete
before running airoha_ppe_hw_init().

Fixes: 00a7678310fe3 ("net: airoha: Introduce flowtable offload support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v2:
- Check for both REG_PPE_PPE_FLOW_CFG(0) and REG_PPE_PPE_FLOW_CFG(1) to
  complete.
- Link to v1: https://lore.kernel.org/r/20260412-airoha-wait-for-npu-config-offload-setup-v1-1-f4e0aa2a5d85@kernel.org
---
 drivers/net/ethernet/airoha/airoha_ppe.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 62cfffb4f0e5..684c8ae9576f 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -1335,6 +1335,29 @@ static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
 	return npu;
 }
 
+static int airoha_ppe_wait_for_npu_init(struct airoha_eth *eth)
+{
+	int err;
+	u32 val;
+
+	/* PPE_FLOW_CFG default register value is 0. Since we reset FE
+	 * during the device probe we can just check the configured value
+	 * is not 0 here.
+	 */
+	err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC,
+				100 * USEC_PER_MSEC, false, eth,
+				REG_PPE_PPE_FLOW_CFG(0));
+	if (err)
+		return err;
+
+	if (airoha_ppe_is_enabled(eth, 1))
+		err = read_poll_timeout(airoha_fe_rr, val, val, USEC_PER_MSEC,
+					100 * USEC_PER_MSEC, false, eth,
+					REG_PPE_PPE_FLOW_CFG(1));
+
+	return err;
+}
+
 static int airoha_ppe_offload_setup(struct airoha_eth *eth)
 {
 	struct airoha_npu *npu = airoha_ppe_npu_get(eth);
@@ -1348,6 +1371,11 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
 	if (err)
 		goto error_npu_put;
 
+	/* Wait for NPU PPE configuration to complete */
+	err = airoha_ppe_wait_for_npu_init(eth);
+	if (err)
+		goto error_npu_put;
+
 	ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
 	if (ppe_num_stats_entries > 0) {
 		err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,

---
base-commit: b9d8b856689d2b968495d79fe653d87fcb8ad98c
change-id: 20260412-airoha-wait-for-npu-config-offload-setup-19d04522412d

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>



^ permalink raw reply related

* Re: [PATCH RFC] ACPI: processor: idle: Do not propagate acpi_processor_ffh_lpi_probe() -ENODEV
From: Sudeep Holla @ 2026-04-14 14:10 UTC (permalink / raw)
  To: Breno Leitao
  Cc: lihuisong (C), Rafael J. Wysocki, Sudeep Holla, Len Brown,
	lpieralisi, catalin.marinas, will, Rafael J. Wysocki, linux-acpi,
	linux-kernel, pjaroszynski, guohanjun, linux-arm-kernel, rmikey,
	kernel-team
In-Reply-To: <ad48gItCwrC-ar34@gmail.com>

On Tue, Apr 14, 2026 at 06:14:19AM -0700, Breno Leitao wrote:
> Hello Sudeep,
> 
> On Tue, Apr 14, 2026 at 01:25:53PM +0100, Sudeep Holla wrote:
> > So while I understand that the kernel did not report an error previously, that
> > does not mean the _LPI table is merely moot on this platform when it contains
> > only a WFI state.
> 
> Can you clarify whether datacenter ARM systems are expected to expose
> deeper idle states beyond WFI in their _LPI tables?
> 

Of course any system that prefers to save power when its idling must have
these _LPI deeper idle states.

> Backing up, I'm observing 72 pr_err() messages during boot on these
> hosts and trying to determine whether this indicates a firmware issue or
> if the kernel needs adjustment.

I consider this a firmware issue, but not a fatal one. What matters more is
the behavior after those errors are reported.

If you force success, either through your change or through the PSCI approach
suggested by lihuisong, then in practice you are only enabling a cpuidle
driver with a single usable state: WFI. That is not inherently wrong, but it
also does not provide much benefit.

When the idle task needs to enter an idle state, it will ask the cpuidle
framework to choose the appropriate state. In this case, however, the
framework has no real decision to make, because the only available state is
WFI. If that is all the platform can support, then the same result can be
achieved more efficiently without registering the cpuidle driver at all, by
falling back to `arch_cpu_idle()`, as I mentioned earlier.

-- 
Regards,
Sudeep


^ permalink raw reply

* Re: [PATCH 3/3] MAINTAINERS: add Axiado SGPIO controller
From: Krzysztof Kozlowski @ 2026-04-14 14:12 UTC (permalink / raw)
  To: Petar Stepanovic, Tzu-Hao Wei, Swark Yang, Prasad Bolisetty,
	Linus Walleij, Bartosz Golaszewski, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Harshit Shah, SriNavmani A
  Cc: linux-gpio, devicetree, linux-arm-kernel, linux-kernel
In-Reply-To: <20260414-axiado-ax3000-sgpio-controller-v1-3-b5c7e4c2e69b@axiado.com>

On 14/04/2026 15:48, Petar Stepanovic wrote:
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 67db88b04537..56835c0a1863 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4234,6 +4234,15 @@ S:	Maintained
>  F:	Documentation/devicetree/bindings/sound/axentia,*
>  F:	sound/soc/atmel/tse850-pcm5142.c
>  
> +AXIADO SGPIO DRIVER
> +M:	Petar Stepanovic <pstepanovic@axiado.com>
> +M:	SriNavmani A <srinavmani@axiado.com>
> +M:	Prasad Bolisetty <pbolisetty@axiado.com>


I also expect reviews from the remaining maintainers, especially in all
the trivialities like posting very old code patterns.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH net-next] net: stmmac: enable RPS and RBU interrupts
From: Russell King (Oracle) @ 2026-04-14 14:13 UTC (permalink / raw)
  To: Sam Edwards
  Cc: Jakub Kicinski, Andrew Lunn, Alexandre Torgue, Andrew Lunn,
	David S. Miller, Eric Dumazet,
	moderated list:BROADCOM BCM2711/BCM2835 ARM ARCHITECTURE,
	linux-stm32, Linux Network Development Mailing List, Paolo Abeni
In-Reply-To: <CAH5Ym4i7VV53hQGY3AjAUW3B8g_ffgmw69kPhPrk2CmcRbguuQ@mail.gmail.com>

Hi Sam,

Most of this email was written this morning, but I didn't have a chance
to finish nor send it due to how busy I am.

I had also written a separate reply last night with detailed results of
what I was seeing but didn't/haven't got around to sending it. Not
currently sure whether I saved it as draft or got rid of it yet.

On Mon, Apr 13, 2026 at 02:54:30PM -0700, Sam Edwards wrote:
> On Mon, Apr 13, 2026, 11:49 Russell King (Oracle) <linux@armlinux.org.uk> wrote:
> >
> > On Mon, Apr 13, 2026 at 11:02:22AM -0700, Jakub Kicinski wrote:
> > > On Fri, 10 Apr 2026 14:07:51 +0100 Russell King (Oracle) wrote:
> > > > Since we are seeing receive buffer exhaustion on several platforms,
> > > > let's enable the interrupts so the statistics we publish via ethtool -S
> > > > actually work to aid diagnosis. I've been in two minds about whether
> > > > to send this patch, but given the problems with stmmac at the moment,
> > > > I think it should be merged.
> > >
> > > Sorry for a under-research response but wasn't there are person trying
> > > to fix the OOM starvation issue? Who was supposed to add a timer?
> > > Is your problem also OOM related or do you suspect something else?
> >
> > It is not OOM related. I have this patch applied:
> >
> > diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > index 131ea887bedc..614d0e10e3e6 100644
> > --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> > @@ -5095,14 +5095,18 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
> >
> >                 if (!buf->page) {
> >                         buf->page = page_pool_alloc_pages(rx_q->page_pool, gfp);
> > -                       if (!buf->page)
> > +                       if (!buf->page) {
> > +                               netdev_err(priv->dev, "q%u: no buffer 1\n", queue);
> >                                 break;
> > +                       }
> >                 }
> >
> >                 if (priv->sph_active && !buf->sec_page) {
> >                         buf->sec_page = page_pool_alloc_pages(rx_q->page_pool, gfp);
> > -                       if (!buf->sec_page)
> > +                       if (!buf->sec_page) {
> > +                               netdev_err(priv->dev, "q%u: no buffer 2\n", queue);
> >                                 break;
> > +                       }
> >
> >                         buf->sec_addr = page_pool_get_dma_addr(buf->sec_page);
> >                 }
> >
> > and it is silent, so we are not suffering starvation of buffers.
> >
> > However, the hardware hangs during iperf3, and because it triggers the
> > MAC to stream PAUSE frames, and my network uses Netgear GS108 and GS116
> > unmanaged switches that always use flow-control between them (there's no
> > way not to) it takes down the entire network - as we've discussed
> > before. So, this problem is pretty fatal to the *entire* network.
> >
> > With this patch, the existing statistical counters for this condition
> > are incremented, and thus users can use ethtool -S to see what happened
> > and report whether they are seeing the same issue.
> >
> > Without this patch applied, there are no diagnostics from stmmac that
> > report what the state is. ethtool -d doesn't list the appropriate
> > registers (as I suspect part of the problem is the number of queues
> > is somewhat dynamic - userspace can change that configuration through
> > ethtool).
> >
> > Thus, one has to resort to using devmem2 to find out what's happened.
> > That's not user friendly.
> >
> > For me, devmem2 shows:
> >
> > Channel 0 status register:
> > Value at address 0x02491160: 0x00000484
> > bit 10: ETI early transmit interrupt - set
> > bit 9 : RWT receive watchdog - clear
> > bit 8 : RPS receieve process stopped - clear
> > bit 7 : RBU receive buffer unavailable - set
> > bit 6 : RI  receive interrupt - clear
> > bit 2 : TBU transmit buffer unavailable - set
> > bit 1 : TPS transmit process stopped - clear
> > bit 0 : TI  transmit interrupt - clear
> 
> Should that reset trigger be RPS, not RBU? My understanding of these
> status bits is RBU is just "RxDMA has failed to take a frame from the
> RxFIFO" while RPS is "the RxFIFO is full." That would make RBU our
> critical threshold to start proactively refilling, and RPS the "too
> late, we lose" threshold.

That's a fine theory, but look at the channel 0 status register above,
noting that any interrupts that are raised but not enabled remain set.
RPS is not set, so RPS is not being raised, only RBU when this
condition occurs.

> Thinking aloud: Do you suppose the RxDMA waits for a wakeup signal
> sent whenever a frame is added to RxFIFO? That might explain why the
> former never recovers once the latter is full: a manual wakeup needs
> to be sent whenever we resolve RBU. Does the .enable_dma_reception()
> op need to be implemented for dwmac5, or have you tried that already?

I've not found anything in the closest documentation I have. The Xavier
is Synopsys IP v5.0, whereas i.MX8M is v5.1 - and v5.1 compared to
previous versions reads the same for statements concerning recovering
from a RBU condition:

"In ring mode, the application should advance the Receive Descriptor
Tail Pointer register of a channel. This bit is set only when the DMA
owns the previous Rx descriptor."

I've tried expanding what happens when RBU fires, dumping some of the
receive state and the receive ring:

[   55.766199] dwc-eth-dwmac 2490000.ethernet eth0: q0: receive buffer unavailable: cur_rx=309 dirty_rx=309 last_cur_rx=245 last_cur_rx_post=309 last_dirty_rx=245 count=64 budget=64

cur_rx == dirty_rx _should_ mean that we fully refilled the ring. These
are their values at the point the RBU interrupt fires.

last_cur_rx and last_dirty_rx are the values of cur_rx/dirty_rx when
stmmac_rx() was last entered.

last_cur_rx_post is the value of cur_rx when stmmac_rx() finished
looping but before we have refilled the ring.

count is the value of count just before stmmac_rx() returns, budget is
the limit at that point.

The patch that prints errors should we fail to allocate a buffer is in
place, none of those errors fire, so we are fully repopulating the ring
each time stmmac_rx() runs.

[   55.766785] RX descriptor ring:
[   55.766802] 000 [0x0000007fffffe000]: 0x0 0x12 0x0 0x340105ee
[   55.766826] 001 [0x0000007fffffe010]: 0x0 0x12 0x0 0x340105ee
[   55.766843] 002 [0x0000007fffffe020]: 0x0 0x12 0x0 0x340105ee
[   55.766860] 003 [0x0000007fffffe030]: 0x0 0x12 0x0 0x340105ee
...
[   55.772205] 308 [0x0000007ffffff340]: 0x0 0x12 0x0 0x340105ee
[   55.772221] 309 [0x0000007ffffff350]: 0x0 0x12 0x0 0x340105ee
[   55.772237] 310 [0x0000007ffffff360]: 0x0 0x12 0x0 0x340105ee
[   55.772253] 311 [0x0000007ffffff370]: 0x0 0x12 0x0 0x340105ee
[   55.772268] 312 [0x0000007ffffff380]: 0x0 0x12 0x0 0x340105ee
[   55.772284] 313 [0x0000007ffffff390]: 0x0 0x12 0x0 0x340105ee
[   55.772300] 314 [0x0000007ffffff3a0]: 0x0 0x12 0x0 0x340105ee
[   55.772315] 315 [0x0000007ffffff3b0]: 0x0 0x12 0x0 0x340105ee
...
[   55.775539] 511 [0x0000007ffffffff0]: 0x0 0x12 0x0 0x340105ee

Every ring entry contains the same RDES3 value, so it really is
completely full at the point RBU fires (bit 31 clear means software
owns the descriptor, and it's basically saying first/last segment,
RDES1 valid, buffer 1 length of 1518.

The Rx tail pointer register contains 0xfffff3a0 which is entry 314.
The current receive descriptor address is also 0xfffff3a0. Note that
these values were obtained some time after the RBU interrupt fired
(due to the time taken for devmem2 to access every stmmac register -
I have a script that dumps the entire stmmac register state via
devmem2.)

The other thing to note is that when looking at debugfs
stmmaceth/eth0/descriptor* (or whatever it's called, I don't have the
NX powered to look at the moment, and I didn't take a copy of it last
night) all tne descriptor entries are fully repopulated with buffers
and owned by the hardware.

I've tried using devmem2 to write to the rx tail pointer to kick it
back into action, but that changes nothing. I've tried writing the
next descriptor value and previous descriptor value, but that appears
to have no effect, it stedfastly remains stuck - and as that is the
documented recovery from RBU and there's no "receive demand" register
listed in dwmac v4 or v5 documentation, there seems to be no other
documented way.

The debug registers that I provided in my previous email suggest that
the MAC is waiting for a packet, and MTL's descriptor reader is idle
(I'm guessing it would only briefly change when the tail pointer is
updated.)

Note that I have augmented the driver with more dma_rmb() + dma_wmb()
in stmmac_rx(), dwmac4_wrback_get_rx_status(), and stmmac_rx_refill()
to ensure that reads and writes to the descriptor ring are correctly
ordered. While this generally allows iperf3 to run for a few more
seconds, it doesn't solve the problem - it is very rare for iperf3
to actually complete before stmmac has taken down my entire network.

I have noticed that on some occasions I see a small number of RBU
interrupts before it falls over.

I'm not going to have much time to look at this today due to further
appointments (I also didn't yesterday - only an hour in the morning
and a bit more time late in the evening/night.) I should have more
time during the rest of the week... but that may change.


From the above, it looks like NAPI/stmmac driver isn't keeping up with
the packet flow coming from an i.MX6 platform (which is limited to
around 470Mbps due to internal SoC bus limitations.)


I'll also mention that stmmac falls apart even more if I run iperf3 -c
-R against an x86 machine that is capable of saturating the network,
so much so that the arm-smmu IOMMU throws errors even after the stmmac
hardware has been soft-reset for addresses that were in the ring
*prior* to the soft-reset occuring (stmmac is soft-reset each time the
netdev is brought up.) The only recovery from that is to reboot -
down/up the interface just spews more IOMMU errors. I don't have the
details of that to hand and I don't have enough time to re-run that
test this morning. From what I remember, the transmit side also stops
processing descriptors (one can see them accumulate in the debugfs
file,) which eventually leads to the netdev watchdog firing.


It currently looks like the stmmac v5 EQoS IP works fine only under
light packet loads. If one puts any stress on it, then the hardware
totally falls apart. This may point to an issue with the AXI bus
configuration that is specific to this platform, but that requires
further investigation.

I'll mention again, in case anyone's forgotten, that these problems
pre-date any of my cleanups I've made to stmmac. From what I remember
they are reproducible with the kernels that are supplied as part of
the nVidia BSP. Again, as I don't have access to the nVidia platform
at the moment, I can't include the details in this email.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


^ permalink raw reply

* Re: [PATCH RFC bpf-next 1/8] kasan: expose generic kasan helpers
From: Alexei Starovoitov @ 2026-04-14 14:36 UTC (permalink / raw)
  To: Alexis Lothoré
  Cc: Andrey Konovalov, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	John Fastabend, David S. Miller, David Ahern, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML, H. Peter Anvin,
	Shuah Khan, Maxime Coquelin, Alexandre Torgue, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Vincenzo Frascino,
	Andrew Morton, ebpf, Bastien Curutchet, Thomas Petazzoni,
	Xu Kuohai, bpf, LKML, Network Development,
	open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
	linux-arm-kernel, kasan-dev, linux-mm
In-Reply-To: <DHSWK17EZUDP.GIJ6BX2NFR6U@bootlin.com>

On Tue, Apr 14, 2026 at 6:13 AM Alexis Lothoré
<alexis.lothore@bootlin.com> wrote:
>
> Hi Andrey, thanks for the prompt review !
>
> On Tue Apr 14, 2026 at 12:19 AM CEST, Andrey Konovalov wrote:
> > On Mon, Apr 13, 2026 at 8:29 PM Alexis Lothoré (eBPF Foundation)
> > <alexis.lothore@bootlin.com> wrote:
> >>
>
> [...]
>
> >> +#ifdef CONFIG_KASAN_GENERIC
> >> +void __asan_load1(void *p);
> >> +void __asan_store1(void *p);
> >> +void __asan_load2(void *p);
> >> +void __asan_store2(void *p);
> >> +void __asan_load4(void *p);
> >> +void __asan_store4(void *p);
> >> +void __asan_load8(void *p);
> >> +void __asan_store8(void *p);
> >> +void __asan_load16(void *p);
> >> +void __asan_store16(void *p);
> >> +#endif /* CONFIG_KASAN_GENERIC */
> >
> > This looks ugly, let's not do this unless it's really required.
> >
> > You can just use kasan_check_read/write() instead - these are public
> > wrappers around the same shadow memory checking functions. And they
> > also work with the SW_TAGS mode, in case the BPF would want to use
> > that mode at some point. (For HW_TAGS, we only have kasan_check_byte()
> > that checks a single byte, but it can be extended in the future if
> > required to be used by BPF.)
>
> ACK, I'll try to use those kasan_check_read and kasan_check_write rather
> than __asan_{load,store}X.

No. The performance penalty will be too high.
hw_tags won't work without corresponding JIT work.
I see no point sacrificing performance for aesthetics.
__asan_load/storeX is what compilers emit.
In that sense JIT is a compiler it should emit exactly the same.


^ permalink raw reply

* Re: [PATCH RFC bpf-next 3/8] bpf: add BPF_JIT_KASAN for KASAN instrumentation of JITed programs
From: Alexei Starovoitov @ 2026-04-14 14:38 UTC (permalink / raw)
  To: Alexis Lothoré
  Cc: Andrey Konovalov, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	John Fastabend, David S. Miller, David Ahern, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML, H. Peter Anvin,
	Shuah Khan, Maxime Coquelin, Alexandre Torgue, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Vincenzo Frascino,
	Andrew Morton, ebpf, Bastien Curutchet, Thomas Petazzoni,
	Xu Kuohai, bpf, LKML, Network Development,
	open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
	linux-arm-kernel, kasan-dev, linux-mm
In-Reply-To: <DHSWSSYRPUVC.2W3G3OU27L3HG@bootlin.com>

On Tue, Apr 14, 2026 at 6:24 AM Alexis Lothoré
<alexis.lothore@bootlin.com> wrote:
>
> On Tue Apr 14, 2026 at 12:20 AM CEST, Andrey Konovalov wrote:
> > On Mon, Apr 13, 2026 at 8:29 PM Alexis Lothoré (eBPF Foundation)
> > <alexis.lothore@bootlin.com> wrote:
> >>
> >> Add a new Kconfig option CONFIG_BPF_JIT_KASAN that automatically enables
> >> KASAN (Kernel Address Sanitizer) memory access checks for JIT-compiled
> >> BPF programs, when both KASAN and JIT compiler are enabled. When
> >> enabled, the JIT compiler will emit shadow memory checks before memory
> >> loads and stores to detect use-after-free, out-of-bounds, and other
> >> memory safety bugs at runtime. The option is gated behind
> >> HAVE_EBPF_JIT_KASAN, as it needs proper arch-specific implementation.
> >>
> >> Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin.com>
> >> ---
> >>  kernel/bpf/Kconfig | 9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >>
> >> diff --git a/kernel/bpf/Kconfig b/kernel/bpf/Kconfig
> >> index eb3de35734f0..28392adb3d7e 100644
> >> --- a/kernel/bpf/Kconfig
> >> +++ b/kernel/bpf/Kconfig
> >> @@ -17,6 +17,10 @@ config HAVE_CBPF_JIT
> >>  config HAVE_EBPF_JIT
> >>         bool
> >>
> >> +# KASAN support for JIT compiler
> >> +config HAVE_EBPF_JIT_KASAN
> >> +       bool
> >> +
> >>  # Used by archs to tell that they want the BPF JIT compiler enabled by
> >>  # default for kernels that were compiled with BPF JIT support.
> >>  config ARCH_WANT_DEFAULT_BPF_JIT
> >> @@ -101,4 +105,9 @@ config BPF_LSM
> >>
> >>           If you are unsure how to answer this question, answer N.
> >>
> >> +config BPF_JIT_KASAN
> >> +       bool
> >> +       depends on HAVE_EBPF_JIT_KASAN
> >> +       default y if BPF_JIT && KASAN_GENERIC
> >
> > Should this be "depends on KASAN && KASAN_GENERIC"?
>
> Meaning, making it an explicit user-selectable option ?
>
> If so, the current design choice is voluntary and based on the feedback
> received on the original RFC, where I have been suggested to
> automatically enable the KASAN instrumentation in BPF programs if KASAN
> support is enabled in the kernel ([1]). But if a user-selectable toggle
> is eventually a better solution, I'm fine with changing it.

Let's not add more config knobs.
Even this patch looks redundant.
Inside JIT do instrumentation when KASAN_GENERIC is set.


^ permalink raw reply

* Re: [PATCH bpf-next v2 2/2] bpf, riscv: Remove redundant bpf_flush_icache() after pack allocator finalize
From: Paul Chaignon @ 2026-04-14 14:48 UTC (permalink / raw)
  To: Puranjay Mohan
  Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Song Liu, Yonghong Song, Jiri Olsa, Xu Kuohai, Catalin Marinas,
	Will Deacon, Luke Nelson, Xi Wang, Björn Töpel,
	Pu Lehui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, linux-arm-kernel, linux-riscv, linux-kernel
In-Reply-To: <20260413191111.3426023-3-puranjay@kernel.org>

On Mon, Apr 13, 2026 at 12:11:09PM -0700, Puranjay Mohan wrote:
> bpf_flush_icache() calls flush_icache_range() to clean the data cache
> and invalidate the instruction cache for the JITed code region. However,
> since commit 48a8f78c50bd ("bpf, riscv: use prog pack allocator in the
> BPF JIT"), this flush is redundant.
> 
> bpf_jit_binary_pack_finalize() copies the JITed instructions to the ROX
> region via bpf_arch_text_copy() -> patch_text_nosync(), and
> patch_text_nosync() already calls flush_icache_range() on the written
> range. The subsequent bpf_flush_icache() repeats the same cache
> maintenance on an overlapping range.
> 
> Remove the redundant bpf_flush_icache() call and its now-unused
> definition.
> 
> Fixes: 48a8f78c50bd ("bpf, riscv: use prog pack allocator in the BPF JIT")
> Acked-by: Song Liu <song@kernel.org>
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>

Tested-by: Paul Chaignon <paul.chaignon@gmail.com>

[...]



^ permalink raw reply

* Re: [PATCH] KVM: arm64: Re-allow hyp tracing HVCs for [nh]VHE
From: Marc Zyngier @ 2026-04-14 14:52 UTC (permalink / raw)
  To: Vincent Donnefort
  Cc: oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team
In-Reply-To: <20260414100231.1859687-1-vdonnefort@google.com>

On Tue, 14 Apr 2026 11:02:31 +0100,
Vincent Donnefort <vdonnefort@google.com> wrote:
> 
> The introduction of __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM excluded hyp
> tracing HVCs from the common [nh]VHE/pKVM list. Re-allow them.
> 
> Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> 
> diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> index 37414440cee7..11dcdf434971 100644
> --- a/arch/arm64/include/asm/kvm_asm.h
> +++ b/arch/arm64/include/asm/kvm_asm.h
> @@ -72,6 +72,14 @@ enum __kvm_host_smccc_func {
>  	__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range,
>  	__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
>  	__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
> +	__KVM_HOST_SMCCC_FUNC___tracing_load,
> +	__KVM_HOST_SMCCC_FUNC___tracing_unload,
> +	__KVM_HOST_SMCCC_FUNC___tracing_enable,
> +	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
> +	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
> +	__KVM_HOST_SMCCC_FUNC___tracing_reset,
> +	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
> +	__KVM_HOST_SMCCC_FUNC___tracing_write_event,
>  	__KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs,
>  	__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
>  	__KVM_HOST_SMCCC_FUNC___vgic_v5_save_apr,
> @@ -100,14 +108,6 @@ enum __kvm_host_smccc_func {
>  	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
>  	__KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid,
> -	__KVM_HOST_SMCCC_FUNC___tracing_load,
> -	__KVM_HOST_SMCCC_FUNC___tracing_unload,
> -	__KVM_HOST_SMCCC_FUNC___tracing_enable,
> -	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
> -	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
> -	__KVM_HOST_SMCCC_FUNC___tracing_reset,
> -	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
> -	__KVM_HOST_SMCCC_FUNC___tracing_write_event,
>  };
>  
>  #define DECLARE_KVM_VHE_SYM(sym)	extern char sym[]
> diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> index 73f2e0221e70..8f7582d57ab5 100644
> --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> @@ -709,6 +709,14 @@ static const hcall_t host_hcall[] = {
>  	HANDLE_FUNC(__kvm_tlb_flush_vmid_range),
>  	HANDLE_FUNC(__kvm_flush_cpu_context),
>  	HANDLE_FUNC(__kvm_timer_set_cntvoff),
> +	HANDLE_FUNC(__tracing_load),
> +	HANDLE_FUNC(__tracing_unload),
> +	HANDLE_FUNC(__tracing_enable),
> +	HANDLE_FUNC(__tracing_swap_reader),
> +	HANDLE_FUNC(__tracing_update_clock),
> +	HANDLE_FUNC(__tracing_reset),
> +	HANDLE_FUNC(__tracing_enable_event),
> +	HANDLE_FUNC(__tracing_write_event),
>  	HANDLE_FUNC(__vgic_v3_save_aprs),
>  	HANDLE_FUNC(__vgic_v3_restore_vmcr_aprs),
>  	HANDLE_FUNC(__vgic_v5_save_apr),
> @@ -735,14 +743,6 @@ static const hcall_t host_hcall[] = {
>  	HANDLE_FUNC(__pkvm_vcpu_load),
>  	HANDLE_FUNC(__pkvm_vcpu_put),
>  	HANDLE_FUNC(__pkvm_tlb_flush_vmid),
> -	HANDLE_FUNC(__tracing_load),
> -	HANDLE_FUNC(__tracing_unload),
> -	HANDLE_FUNC(__tracing_enable),
> -	HANDLE_FUNC(__tracing_swap_reader),
> -	HANDLE_FUNC(__tracing_update_clock),
> -	HANDLE_FUNC(__tracing_reset),
> -	HANDLE_FUNC(__tracing_enable_event),
> -	HANDLE_FUNC(__tracing_write_event),
>  };

Why isn't it sufficient to reorder the enum?

Thanks,

	M.

-- 
Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH v2 2/7] dt-bindings: soc: samsung: exynos-pmu: add samsung,pmu-intr-gen phandle
From: Alexey Klimov @ 2026-04-14 14:54 UTC (permalink / raw)
  To: Rob Herring
  Cc: Sam Protsenko, linux-samsung-soc, Krzysztof Kozlowski,
	Peter Griffin, André Draszik, Conor Dooley, Alim Akhtar,
	Tudor Ambarus, Krzysztof Kozlowski, linux-arm-kernel, devicetree,
	linux-kernel
In-Reply-To: <20260413221638.GA3624532-robh@kernel.org>

On Mon Apr 13, 2026 at 11:16 PM BST, Rob Herring wrote:
> On Wed, Apr 01, 2026 at 05:51:55AM +0100, Alexey Klimov wrote:
>> Some Exynos-based SoCs, for instance Exynos850, require access
>> to the pmu interrupt generation register region which is exposed
>> as a syscon. Update the exynos-pmu bindings documentation to
>> reflect this.
>> 
>> Signed-off-by: Alexey Klimov <alexey.klimov@linaro.org>
>> ---
>>  .../devicetree/bindings/soc/samsung/exynos-pmu.yaml    | 18 ++++++++++++++++++
>>  1 file changed, 18 insertions(+)
>> 
>> diff --git a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
>> index 76ce7e98c10f..92acdfd5d44e 100644
>> --- a/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
>> +++ b/Documentation/devicetree/bindings/soc/samsung/exynos-pmu.yaml
>> @@ -110,6 +110,11 @@ properties:
>>      description:
>>        Node for reboot method
>>  
>> +  samsung,pmu-intr-gen-syscon:
>> +    $ref: /schemas/types.yaml#/definitions/phandle
>> +    description:
>> +      Phandle to PMU interrupt generation interface.
>> +
>>    google,pmu-intr-gen-syscon:
>
> Does this mean the driver is just going to have to look at both 
> properties for the same thing? If so, just use the existing property. We 
> don't need 2. Yeah, 'google' in Samsung SoCs is a bit weird, but that's 
> Samsung's fault for not upstreaming support for their h/w first.

First question - yes, look for both properties. Using the existing
property is even better, I don't mind at all. Thanks for pointing that
out.

Initially, I added more generic samsung,... property because I thought
that device tree style prefers <vendor>,<property-name> semantics where
<vendor> is actual (real) HW vendor of corresponding hw block and it
should also refer to the first/earlier hw vendor in terms of the
timeline.

Using google,<..> is simplier and I don't need need commit that
obsoletes that, so I'll rework the series in that way.

BR,
Alexey



^ permalink raw reply

* Re: [PATCH] KVM: arm64: Re-allow hyp tracing HVCs for [nh]VHE
From: Vincent Donnefort @ 2026-04-14 14:58 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: oliver.upton, joey.gouly, suzuki.poulose, yuzenghui,
	catalin.marinas, will, linux-arm-kernel, kvmarm, kernel-team
In-Reply-To: <86ik9t387m.wl-maz@kernel.org>

On Tue, Apr 14, 2026 at 03:52:29PM +0100, Marc Zyngier wrote:
> On Tue, 14 Apr 2026 11:02:31 +0100,
> Vincent Donnefort <vdonnefort@google.com> wrote:
> > 
> > The introduction of __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM excluded hyp
> > tracing HVCs from the common [nh]VHE/pKVM list. Re-allow them.
> > 
> > Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
> > 
> > diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
> > index 37414440cee7..11dcdf434971 100644
> > --- a/arch/arm64/include/asm/kvm_asm.h
> > +++ b/arch/arm64/include/asm/kvm_asm.h
> > @@ -72,6 +72,14 @@ enum __kvm_host_smccc_func {
> >  	__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range,
> >  	__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
> >  	__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_load,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_unload,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_enable,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_reset,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
> > +	__KVM_HOST_SMCCC_FUNC___tracing_write_event,
> >  	__KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs,
> >  	__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
> >  	__KVM_HOST_SMCCC_FUNC___vgic_v5_save_apr,
> > @@ -100,14 +108,6 @@ enum __kvm_host_smccc_func {
> >  	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
> >  	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
> >  	__KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_load,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_unload,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_enable,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_reset,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
> > -	__KVM_HOST_SMCCC_FUNC___tracing_write_event,
> >  };
> >  
> >  #define DECLARE_KVM_VHE_SYM(sym)	extern char sym[]
> > diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > index 73f2e0221e70..8f7582d57ab5 100644
> > --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c
> > @@ -709,6 +709,14 @@ static const hcall_t host_hcall[] = {
> >  	HANDLE_FUNC(__kvm_tlb_flush_vmid_range),
> >  	HANDLE_FUNC(__kvm_flush_cpu_context),
> >  	HANDLE_FUNC(__kvm_timer_set_cntvoff),
> > +	HANDLE_FUNC(__tracing_load),
> > +	HANDLE_FUNC(__tracing_unload),
> > +	HANDLE_FUNC(__tracing_enable),
> > +	HANDLE_FUNC(__tracing_swap_reader),
> > +	HANDLE_FUNC(__tracing_update_clock),
> > +	HANDLE_FUNC(__tracing_reset),
> > +	HANDLE_FUNC(__tracing_enable_event),
> > +	HANDLE_FUNC(__tracing_write_event),
> >  	HANDLE_FUNC(__vgic_v3_save_aprs),
> >  	HANDLE_FUNC(__vgic_v3_restore_vmcr_aprs),
> >  	HANDLE_FUNC(__vgic_v5_save_apr),
> > @@ -735,14 +743,6 @@ static const hcall_t host_hcall[] = {
> >  	HANDLE_FUNC(__pkvm_vcpu_load),
> >  	HANDLE_FUNC(__pkvm_vcpu_put),
> >  	HANDLE_FUNC(__pkvm_tlb_flush_vmid),
> > -	HANDLE_FUNC(__tracing_load),
> > -	HANDLE_FUNC(__tracing_unload),
> > -	HANDLE_FUNC(__tracing_enable),
> > -	HANDLE_FUNC(__tracing_swap_reader),
> > -	HANDLE_FUNC(__tracing_update_clock),
> > -	HANDLE_FUNC(__tracing_reset),
> > -	HANDLE_FUNC(__tracing_enable_event),
> > -	HANDLE_FUNC(__tracing_write_event),
> >  };
> 
> Why isn't it sufficient to reorder the enum?
> 
> Thanks,
> 
> 	M.

It is, I just thought we might want to keep both in the same order. WDYS?

> 
> -- 
> Without deviation from the norm, progress is not possible.


^ permalink raw reply

* Re: [PATCH RFC bpf-next 1/8] kasan: expose generic kasan helpers
From: Andrey Konovalov @ 2026-04-14 15:10 UTC (permalink / raw)
  To: Alexei Starovoitov
  Cc: Alexis Lothoré, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Song Liu, Yonghong Song, Jiri Olsa,
	John Fastabend, David S. Miller, David Ahern, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, Dave Hansen, X86 ML, H. Peter Anvin,
	Shuah Khan, Maxime Coquelin, Alexandre Torgue, Andrey Ryabinin,
	Alexander Potapenko, Dmitry Vyukov, Vincenzo Frascino,
	Andrew Morton, ebpf, Bastien Curutchet, Thomas Petazzoni,
	Xu Kuohai, bpf, LKML, Network Development,
	open list:KERNEL SELFTEST FRAMEWORK, linux-stm32,
	linux-arm-kernel, kasan-dev, linux-mm
In-Reply-To: <CAADnVQLJ=fJ7t1i2+_RYqU1gqYqiLP9Zrwo4vdZsgzjK_yzJTQ@mail.gmail.com>

On Tue, Apr 14, 2026 at 4:36 PM Alexei Starovoitov
<alexei.starovoitov@gmail.com> wrote:
>
> > ACK, I'll try to use those kasan_check_read and kasan_check_write rather
> > than __asan_{load,store}X.
>
> No. The performance penalty will be too high.

With using __asan_load/storeX(), it will be one function call to get
to check_region_inline(): __asan_load/storeX->check_region_inline.

With kasan_check_read/write(), right now, it would be two function
calls: __kasan_check_read->kasan_check_range->check_region_inline.

I doubt an extra function call would make a difference in terms of
performance: the shadow checking itself is also expensive.

But if the second call is a concern, we can move kasan_check_range()
and lower-level functions into mm/kasan/generic.h and include it into
shadow.c, and then it will be just one function call.

To improve performance further, the JIT compiler could emit inlined
shadow checking instructions, same as the C compiler does with
KASAN_INLINE=y.

> hw_tags won't work without corresponding JIT work.

You probably meant SW_TAGS here.

HW_TAGS will likely just work without any JIT changes (even the
kasan_check_byte() thing I mentioned should not be required), assuming
JIT'ed BPF code just accesses kernel-returned pointers as is.

> I see no point sacrificing performance for aesthetics.

With the change I suggested above, there would be no performance
difference. And the code stays cleaner.

> __asan_load/storeX is what compilers emit.

For Generic mode. For SW_TAGS, the function names are different.
Keeping this detail within the KASAN code is cleaner.


> In that sense JIT is a compiler it should emit exactly the same.


^ permalink raw reply

* Re: [PATCH rc v1 3/4] iommu/arm-smmu-v3: Retain SMMUEN during kdump device reset
From: Nicolin Chen @ 2026-04-14 15:16 UTC (permalink / raw)
  To: Tian, Kevin
  Cc: jgg@nvidia.com, will@kernel.org, robin.murphy@arm.com,
	jamien@nvidia.com, joro@8bytes.org, praan@google.com,
	baolu.lu@linux.intel.com, smostafa@google.com,
	miko.lenczewski@arm.com, linux-arm-kernel@lists.infradead.org,
	iommu@lists.linux.dev, linux-kernel@vger.kernel.org,
	stable@vger.kernel.org
In-Reply-To: <BN9PR11MB527631CAE6281C630FB148B88C592@BN9PR11MB5276.namprd11.prod.outlook.com>

On Fri, Apr 10, 2026 at 06:21:43AM +0000, Tian, Kevin wrote:
> > From: Nicolin Chen <nicolinc@nvidia.com>
> > Sent: Friday, April 10, 2026 3:47 AM
> > 
> >  	/* Clear CR0 and sync (disables SMMU and queue processing) */
> >  	reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
> >  	if (reg & CR0_SMMUEN) {
> >  		dev_warn(smmu->dev, "SMMU currently enabled!
> > Resetting...\n");
> 
> move to after the check of kdump kernel
> 
> > @@ -5038,6 +5064,11 @@ static int arm_smmu_device_reset(struct
> > arm_smmu_device *smmu)
> >  		return ret;
> >  	}
> > 
> > +	/*
> > +	 * Disable EVTQ and PRIQ in kdump kernel. The old kernel's CDs and
> > page
> > +	 * tables may be corrupted, which could trigger event spamming.
> > PRIQ is
> > +	 * also useless since we cannot service page requests during kdump.
> > +	 */
> >  	if (is_kdump_kernel())
> >  		enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
> > 
> 
> then just don't enable them in earlier lines?

I will incorporate these (and the other comments) into v2.

Thanks!
Nicolin


^ permalink raw reply

* [PATCH v22 2/7] dt-bindings: remoteproc: st,stm32-rproc: add st,rproc-tee
From: Arnaud Pouliquen @ 2026-04-14 15:28 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

Add st,rproc-tee to describe the remoteprocessor control through the TEE
remoteproc backend.

The property is a phandle to the TEE remoteproc node with one argument
cell carrying the remote processor identifier.

When st,rproc-tee is present, Linux must not manage MCU reset/holdboot
directly. Update schema conditionals accordingly:
- do not require resets unconditionally
- forbid resets, reset-names and st,syscfg-holdboot when st,rproc-tee
  is present
- keep legacy holdboot checks for non-TEE configurations

Also add a DT example showing the TEE-based configuration.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 .../bindings/remoteproc/st,stm32-rproc.yaml   | 55 ++++++++++++++++---
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
index 843679c557e7..7fe54d529e04 100644
--- a/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
@@ -143,24 +143,45 @@ properties:
     maxItems: 1
     description: Default name of the remote processor firmware.
 
+  st,rproc-tee:
+    description:
+      Reference the remote processor node on TEE bus. The value is a phandle
+      reference to the remote processor node, followed by a cell specifying
+      the remote processor device identifier used by the TEE.
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: Phandle of the remote processor node on the TEE bus
+          - description: Remote processor device identifier used by the TEE
+
 required:
   - compatible
   - reg
-  - resets
 
 allOf:
   - if:
-      properties:
-        reset-names:
-          not:
-            contains:
-              const: hold_boot
-    then:
       required:
-        - st,syscfg-holdboot
-    else:
+        - st,rproc-tee
+    then:
       properties:
+        resets: false
+        reset-names: false
         st,syscfg-holdboot: false
+    else:
+      required:
+        - resets
+      if:
+        properties:
+          reset-names:
+            not:
+              contains:
+                const: hold_boot
+      then:
+        required:
+          - st,syscfg-holdboot
+      else:
+        properties:
+          st,syscfg-holdboot: false
 
 additionalProperties: false
 
@@ -192,5 +213,21 @@ examples:
       st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
       st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>;
     };
+  - |
+    firmware {
+      tee_rproc: optee-rproc {
+        compatible = "80a4c275-0a47-4905-8285-1486a9771a08";
+      };
+    };
+
+    m4@10000000 {
+      compatible = "st,stm32mp1-m4";
+      reg = <0x10000000 0x40000>,
+            <0x30000000 0x40000>,
+            <0x38000000 0x10000>;
+      st,rproc-tee = <&tee_rproc 0>;
+      st,syscfg-rsc-tbl = <&tamp 0x144 0xFFFFFFFF>;
+      st,syscfg-m4-state = <&tamp 0x148 0xFFFFFFFF>;
+    };
 
 ...
-- 
2.43.0



^ permalink raw reply related

* [PATCH v22 4/7] remoteproc: Introduce optional release_fw operation
From: Arnaud Pouliquen @ 2026-04-14 15:28 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

The release_fw operation allows releasing remote processor resources
configured during rproc_parse_fw() and rproc_load_segments().
For example, it can release carveouts mapped during these operations.

This operation is invoked in the following cases:
 - When an error occurs during remote processor boot.
 - When an error occurs during remote processor recovery start.
 - After stopping the remote processor.

This operation is required for the remoteproc_tee implementation following
a stop or upon encountering an error. Since the remoteproc image is loaded
during resource table parsing, multiple failure scenarios may occur prior
to remote processor startup, including issues with resource handling and
carveout allocation.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>

---

Updates from version 18:
- Rewrite rproc_ops::release_fw documentation
- Improve commit message

Updates from version 16:
- Removed the rproc:load_fw() ops introduced in previous version.
- Removed duplicate calls to rproc_release_fw in rproc_fw_boot and rproc_boot.
---
 drivers/remoteproc/remoteproc_core.c     | 6 ++++++
 drivers/remoteproc/remoteproc_internal.h | 6 ++++++
 include/linux/remoteproc.h               | 5 +++++
 3 files changed, 17 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index ec1860e1cfa9..93ab505ff014 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1856,6 +1856,8 @@ static int rproc_boot_recovery(struct rproc *rproc)
 
 	/* boot the remote processor up again */
 	ret = rproc_start(rproc, firmware_p);
+	if (ret)
+		rproc_release_fw(rproc);
 
 	release_firmware(firmware_p);
 
@@ -1997,6 +1999,8 @@ int rproc_boot(struct rproc *rproc)
 		}
 
 		ret = rproc_fw_boot(rproc, firmware_p);
+		if (ret)
+			rproc_release_fw(rproc);
 
 		release_firmware(firmware_p);
 	}
@@ -2066,6 +2070,8 @@ int rproc_shutdown(struct rproc *rproc)
 
 	rproc_disable_iommu(rproc);
 
+	rproc_release_fw(rproc);
+
 	/* Free the copy of the resource table */
 	kfree(rproc->cached_table);
 	rproc->cached_table = NULL;
diff --git a/drivers/remoteproc/remoteproc_internal.h b/drivers/remoteproc/remoteproc_internal.h
index 0cd09e67ac14..c7fb908f8652 100644
--- a/drivers/remoteproc/remoteproc_internal.h
+++ b/drivers/remoteproc/remoteproc_internal.h
@@ -221,4 +221,10 @@ bool rproc_u64_fit_in_size_t(u64 val)
 	return (val <= (size_t) -1);
 }
 
+static inline void rproc_release_fw(struct rproc *rproc)
+{
+	if (rproc->ops->release_fw)
+		rproc->ops->release_fw(rproc);
+}
+
 #endif /* REMOTEPROC_INTERNAL_H */
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index 8fd0d7f63c8e..a2bb51a113b1 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -381,6 +381,10 @@ enum rsc_handling_status {
  * @panic:	optional callback to react to system panic, core will delay
  *		panic at least the returned number of milliseconds
  * @coredump:	  collect firmware dump after the subsystem is shutdown
+ * @release_fw:	Optional function to release resources allocated during
+ *		parse_fw() or load() operations. This function is called after
+ *		stopping the remote processor or in case of an error during the
+ *		boot or recovery sequence.
  */
 struct rproc_ops {
 	int (*prepare)(struct rproc *rproc);
@@ -403,6 +407,7 @@ struct rproc_ops {
 	u64 (*get_boot_addr)(struct rproc *rproc, const struct firmware *fw);
 	unsigned long (*panic)(struct rproc *rproc);
 	void (*coredump)(struct rproc *rproc);
+	void (*release_fw)(struct rproc *rproc);
 };
 
 /**
-- 
2.43.0



^ permalink raw reply related

* [PATCH v22 3/7] remoteproc: core: Introduce rproc_pa_to_va helper
From: Arnaud Pouliquen @ 2026-04-14 15:28 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

When a resource table is loaded by an external entity such as U-boot or
OP-TEE, we do not necessarily get the device address(da) but the physical
address(pa).
This helper performs similar translation than the rproc_da_to_va()
but based on a physical address.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
V22 updates:
-  use size_t for offset and remove its comparaison with 0
---
 drivers/remoteproc/remoteproc_core.c | 50 ++++++++++++++++++++++++++++
 include/linux/remoteproc.h           |  1 +
 2 files changed, 51 insertions(+)

diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index b087ed21858a..ec1860e1cfa9 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -225,6 +225,56 @@ void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
 }
 EXPORT_SYMBOL(rproc_da_to_va);
 
+/**
+ * rproc_pa_to_va() - lookup the kernel virtual address for a physical address of a remoteproc
+ * memory
+ *
+ * @rproc: handle of a remote processor
+ * @pa: remoteproc physical address
+ * @len: length of the memory region @pa is pointing to
+ * @is_iomem: optional pointer filled in to indicate if @pa is iomapped memory
+ *
+ * This function is a helper function similar to rproc_da_to_va() but it deals with physical
+ * addresses instead of device addresses.
+ *
+ * Return: a valid kernel address on success or NULL on failure
+ */
+void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem)
+{
+	struct rproc_mem_entry *carveout;
+	void *ptr = NULL;
+	size_t offset;
+
+	list_for_each_entry(carveout, &rproc->carveouts, node) {
+		/* Verify that carveout is allocated */
+		if (!carveout->va)
+			continue;
+
+		/* try next carveout if pa is too small */
+		if (pa < carveout->dma)
+			continue;
+
+		offset = pa - carveout->dma;
+
+		/* try next carveout if pa is too large */
+		if (offset > carveout->len)
+			continue;
+
+		if (len > carveout->len - offset)
+			continue;
+
+		ptr = carveout->va + offset;
+
+		if (is_iomem)
+			*is_iomem = carveout->is_iomem;
+
+		break;
+	}
+
+	return ptr;
+}
+EXPORT_SYMBOL(rproc_pa_to_va);
+
 /**
  * rproc_find_carveout_by_name() - lookup the carveout region by a name
  * @rproc: handle of a remote processor
diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h
index b4795698d8c2..8fd0d7f63c8e 100644
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -690,6 +690,7 @@ int rproc_detach(struct rproc *rproc);
 int rproc_set_firmware(struct rproc *rproc, const char *fw_name);
 void rproc_report_crash(struct rproc *rproc, enum rproc_crash_type type);
 void *rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem);
+void *rproc_pa_to_va(struct rproc *rproc, phys_addr_t pa, size_t len, bool *is_iomem);
 
 /* from remoteproc_coredump.c */
 void rproc_coredump_cleanup(struct rproc *rproc);
-- 
2.43.0



^ permalink raw reply related

* [PATCH v22 6/7] remoteproc: stm32: Create sub-functions to request shutdown and release
From: Arnaud Pouliquen @ 2026-04-14 15:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

To prepare for the support of TEE remoteproc, create sub-functions
that can be used in both cases, with and without remoteproc TEE support.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
 drivers/remoteproc/stm32_rproc.c | 82 +++++++++++++++++++-------------
 1 file changed, 49 insertions(+), 33 deletions(-)

diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 632614013dc6..4bcd6a784935 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -209,6 +209,52 @@ static int stm32_rproc_mbox_idx(struct rproc *rproc, const unsigned char *name)
 	return -EINVAL;
 }
 
+static void stm32_rproc_request_shutdown(struct rproc *rproc)
+{
+	struct stm32_rproc *ddata = rproc->priv;
+	int err, idx;
+
+	/* Request shutdown of the remote processor */
+	if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) {
+		idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
+		if (idx >= 0 && ddata->mb[idx].chan) {
+			err = mbox_send_message(ddata->mb[idx].chan, "detach");
+			if (err < 0)
+				dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
+		}
+	}
+}
+
+static int stm32_rproc_release(struct rproc *rproc)
+{
+	struct stm32_rproc *ddata = rproc->priv;
+	int err = 0;
+
+	/* To allow platform Standby power mode, set remote proc Deep Sleep */
+	if (ddata->pdds.map) {
+		err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
+					 ddata->pdds.mask, 1);
+		if (err) {
+			dev_err(&rproc->dev, "failed to set pdds\n");
+			return err;
+		}
+	}
+
+	/* Update coprocessor state to OFF if available */
+	if (ddata->m4_state.map) {
+		err = regmap_update_bits(ddata->m4_state.map,
+					 ddata->m4_state.reg,
+					 ddata->m4_state.mask,
+					 M4_STATE_OFF);
+		if (err) {
+			dev_err(&rproc->dev, "failed to set copro state\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
 static int stm32_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
@@ -511,17 +557,9 @@ static int stm32_rproc_detach(struct rproc *rproc)
 static int stm32_rproc_stop(struct rproc *rproc)
 {
 	struct stm32_rproc *ddata = rproc->priv;
-	int err, idx;
+	int err;
 
-	/* request shutdown of the remote processor */
-	if (rproc->state != RPROC_OFFLINE && rproc->state != RPROC_CRASHED) {
-		idx = stm32_rproc_mbox_idx(rproc, STM32_MBX_SHUTDOWN);
-		if (idx >= 0 && ddata->mb[idx].chan) {
-			err = mbox_send_message(ddata->mb[idx].chan, "detach");
-			if (err < 0)
-				dev_warn(&rproc->dev, "warning: remote FW shutdown without ack\n");
-		}
-	}
+	stm32_rproc_request_shutdown(rproc);
 
 	err = stm32_rproc_set_hold_boot(rproc, true);
 	if (err)
@@ -533,29 +571,7 @@ static int stm32_rproc_stop(struct rproc *rproc)
 		return err;
 	}
 
-	/* to allow platform Standby power mode, set remote proc Deep Sleep */
-	if (ddata->pdds.map) {
-		err = regmap_update_bits(ddata->pdds.map, ddata->pdds.reg,
-					 ddata->pdds.mask, 1);
-		if (err) {
-			dev_err(&rproc->dev, "failed to set pdds\n");
-			return err;
-		}
-	}
-
-	/* update coprocessor state to OFF if available */
-	if (ddata->m4_state.map) {
-		err = regmap_update_bits(ddata->m4_state.map,
-					 ddata->m4_state.reg,
-					 ddata->m4_state.mask,
-					 M4_STATE_OFF);
-		if (err) {
-			dev_err(&rproc->dev, "failed to set copro state\n");
-			return err;
-		}
-	}
-
-	return 0;
+	return stm32_rproc_release(rproc);
 }
 
 static void stm32_rproc_kick(struct rproc *rproc, int vqid)
-- 
2.43.0



^ permalink raw reply related

* [PATCH v22 0/7] Introduction of a remoteproc tee to load signed firmware
From: Arnaud Pouliquen @ 2026-04-14 15:28 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen

Main updates from version V21[1]:
--------------------------------
This version removes the st,stm32mp1-m4-tee compatibility string,
which no longer seems to be accepted by the Devicetree maintainers.
As a consequence, the stm32-rproc-tee driver, introduced to simplify
the code, is removed. The STM32 integration reuses the existing
stm32_rproc driver implemented in V19.

The devicetree is now structured as follows:

    firmware {
        tee_rproc: optee-rproc {
            compatible = "80a4c275-0a47-4905-8285-1486a9771a08";
        };
    };

    m4: m4@10000000 {
      compatible = "st,stm32mp1-m4";
      reg = <0x10000000 0x40000>,
            <0x30000000 0x40000>,
            <0x38000000 0x10000>;

      mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>, <&ipcc 3>;
      mbox-names = "vq0", "vq1", "shutdown", "detach";

      memory-region = <&vdev0vring0>, <&m_ipc_shm>, <&mcuram2>,
                      <&vdev0vring1>, <&vdev0buffer>, <&retram>;

      interrupt-parent = <&exti>;
      interrupts = <68 1>;

      st,rproc-tee = <&tee_rproc 0>;

      status = "okay";
    };

As a consequence, this version:
- reintroduce v19 commits for stm32_rproc.c driver , adding the support
  of the st,rproc-tee binding.
- drops the dedicated remoteproc-tee.yaml and st,stm32-rproc-tee.yaml
  bindings from the series.
- extends st,stm32-rproc.yaml with st,rproc-tee to describe the link to
  the TEE remoteproc backend.
- removes the dedicated stm32_rproc_tee.c driver and reuses stm32_rproc.c
  for both native and TEE-controlled cases.
- keeps remoteproc_tee.c aligned with the phandle-based lookup introduced
  in v21 and uses a device_link between the STM32 remoteproc instance and
  the TEE backend device.

More details are available in each patch commit message.

Main updates from version V20[3]:
--------------------------------
To address Rob’s concern on v20concerning resource declaration under the
tee node, the device tree is now structured as follows,replacing the
child-parent hierarchy with a phandle:

    firmware {
        tee_rproc: optee-rproc {
            compatible = "80a4c275-0a47-4905-8285-1486a9771a08";
        };
    };

    m4: m4@0 {
      compatible = "st,stm32mp1-m4-tee";
      reg = <0 0>;

      mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
      mbox-names = "vq0", "vq1", "shutdown";

      memory-region = <&vdev0vring0>, <&m_ipc_shm>, <&mcuram2>,
                      <&vdev0vring1>, <&vdev0buffer>, <&retram>;

      interrupt-parent = <&exti>;
      interrupts = <68 1>;

      rproc-tee-phandle = <&tee_rproc 0>;
      st,auto-boot;
      wakeup-source;

      status = "okay";
    };

As a consequence, this version:
- Updates the device tree and bindings to:
  - Change the compatible property from
    "rproc-service-80a4c275-0a47-4905-8285-1486a9771a08" to
    "80a4c275-0a47-4905-8285-1486a9771a08".
  - Use the rproc-tee-phandle to avoid the parent-child hierarchy.
- Updates stm32_rproc_tee.c and remoteproc_tee.c to adapt to the new bindings.
- Updates remoteproc_tee.c to compute the device tree compatible string from
  the TEE UUID.

Main updates from version V19[4]:
--------------------------------
The devicetree is now structured as follows:

	firmware {
		optee {
			compatible = "linaro,optee-tz";
			method = "smc";
			#address-cells = <1>;
			#size-cells = <0>;
			rproc-service@0 {
				compatible = "rproc-service-80a4c275-0a47-4905-8285-1486a9771a08";
				reg = <0>;
				#address-cells = <1>;
				#size-cells = <0>;
				status = "okay";
				m4: m4@0 {
					compatible = "st,stm32mp15-m4-tee";
					reg = <0>;
					mboxes = <&ipcc 0>, <&ipcc 1>, <&ipcc 2>;
					mbox-names = "vq0", "vq1", "shutdown";
					memory-region = <&vdev0vring0>,	<&m_ipc_shm>, <&mcuram2>,
							<&vdev0vring1>, <&vdev0buffer>, <&retram>;
					interrupt-parent = <&exti>;
					interrupts = <68 1>;
					status = "okay";
				};
			};
		};
	};

As a consequence, this version:

- Introduces a new stm32_rproc_tee.c remoteproc driver.

  Instead of further complicating the existing stm32_rproc.c driver, a
  dedicated TEE-based driver is added. Both drivers are intended to also
  support the STM32MP2x Cortex-M33 remote processor in a next step.

- Reworks the bindings:
  - Drop the st,stm32-rproc.yaml updates that were introduced in previous
    revisions.
  - Add remoteproc-tee.yaml for the
    "rproc-service-80a4c275-0a47-4905-8285-1486a9771a08" compatible.
  - Add st,stm32-rproc-tee.yaml for the "st,stm32mp15-m4-tee" compatible.

- Reworks the probing sequence:

  The m4@0 device is now probed by the remoteproc-tee driver, which itself
  is instantiated by the TEE (OP-TEE) bus.

More details are available in each patch commit message.

[1] https://lore.kernel.org/linux-remoteproc/20260317180329.1207625-1-arnaud.pouliquen@foss.st.com/
[2] https://lore.kernel.org/linux-remoteproc/20251217153917.3998544-1-arnaud.pouliquen@foss.st.com/
[3] https://lore.kernel.org/linux-devicetree/20250625094028.758016-1-arnaud.pouliquen@foss.st.com/


Tested-on:
---------
commit 591cd656a1bf ("Linux 7.0-rc7")

Description of the feature:
--------------------------
This series proposes the implementation of a remoteproc tee driver to
communicate with a TEE trusted application responsible for authenticating
and loading the remoteproc firmware image in an Arm secure context.

1) Principle:

The remoteproc tee driver provides services to communicate with the OP-TEE
trusted application running on the Trusted Execution Context (TEE).
The trusted application in TEE manages the remote processor lifecycle:

- authenticating and loading firmware images,
- isolating and securing the remote processor memories,
- supporting multi-firmware (e.g., TF-M + Zephyr on a Cortex-M33),
- managing the start and stop of the firmware by the TEE.

2) Format of the signed image:

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/ta/remoteproc/src/remoteproc_core.c#L18-L57

3) OP-TEE trusted application API:

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/ta/remoteproc/include/ta_remoteproc.h

4) OP-TEE signature script

Refer to:
https://github.com/OP-TEE/optee_os/blob/master/scripts/sign_rproc_fw.py

Example of usage:
sign_rproc_fw.py --in <fw1.elf> --in <fw2.elf> --out <signed_fw.sign> --key ${OP-TEE_PATH}/keys/default.pem


5) Impact on User space Application

No sysfs impact. The user only needs to provide the signed firmware image
instead of the ELF image.


For more information about the implementation, a presentation is available here
(note that the format of the signed image has evolved between the presentation
and the integration in OP-TEE).

https://resources.linaro.org/en/resource/6c5bGvZwUAjX56fvxthxds

Arnaud Pouliquen (7):
  dt-bindings: firmware: Add TEE remoteproc service binding
  dt-bindings: remoteproc: st,stm32-rproc: add st,rproc-tee
  remoteproc: core: Introduce rproc_pa_to_va helper
  remoteproc: Introduce optional release_fw operation
  remoteproc: Add TEE support
  remoteproc: stm32: Create sub-functions to request shutdown and
    release
  remoteproc: stm32: Add support of an OP-TEE TA to load the firmware

 .../bindings/remoteproc/remoteproc-tee.yaml   |  36 +
 .../bindings/remoteproc/st,stm32-rproc.yaml   |  55 +-
 drivers/remoteproc/Kconfig                    |  10 +
 drivers/remoteproc/Makefile                   |   1 +
 drivers/remoteproc/remoteproc_core.c          |  56 ++
 drivers/remoteproc/remoteproc_internal.h      |   6 +
 drivers/remoteproc/remoteproc_tee.c           | 789 ++++++++++++++++++
 drivers/remoteproc/stm32_rproc.c              | 249 ++++--
 include/linux/remoteproc.h                    |   6 +
 include/linux/remoteproc_tee.h                |  98 +++
 10 files changed, 1220 insertions(+), 86 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/remoteproc-tee.yaml
 create mode 100644 drivers/remoteproc/remoteproc_tee.c
 create mode 100644 include/linux/remoteproc_tee.h


base-commit: 591cd656a1bf5ea94a222af5ef2ee76df029c1d2
-- 
2.43.0



^ permalink raw reply

* [PATCH v22 1/7] dt-bindings: firmware: Add TEE remoteproc service binding
From: Arnaud Pouliquen @ 2026-04-14 15:28 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

Add a device tree binding for the TEE-based remote processor control
service implemented as an OP-TEE Trusted Application identified by
UUID 80a4c275-0a47-4905-8285-1486a9771a08.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
v21 updates:
- rename compatible to exactly match with the TEE UUID
- the remoteproc device driver is no more declared as a child,
  but use phandle as done for the SCMI.
- remove linaro,optee-tz bindings update are now useless.
---
 .../bindings/remoteproc/remoteproc-tee.yaml   | 36 +++++++++++++++++++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/remoteproc-tee.yaml

diff --git a/Documentation/devicetree/bindings/remoteproc/remoteproc-tee.yaml b/Documentation/devicetree/bindings/remoteproc/remoteproc-tee.yaml
new file mode 100644
index 000000000000..498a7e590905
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/remoteproc-tee.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/remoteproc-tee.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TEE Remote Processor Control Service (UUID 80a4c275-0a47-4905-8285-1486a9771a08)
+
+maintainers:
+  - Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
+
+description:
+  Node describing a TEE-based remote processor control service implemented as
+  a Trusted Application identified by UUID 80a4c275-0a47-4905-8285-1486a9771a08.
+
+  This binding is intended to define the interface for remoteproc services
+  implemented as TAs running in a TEE, and is used by the a remoteproc driver
+  to bind to such a service and control a remote processor through it.
+
+properties:
+  compatible:
+    const: 80a4c275-0a47-4905-8285-1486a9771a08
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    firmware {
+        tee_rproc: optee-rproc {
+            compatible = "80a4c275-0a47-4905-8285-1486a9771a08";
+        };
+    };
+...
-- 
2.43.0



^ permalink raw reply related

* [PATCH v22 7/7] remoteproc: stm32: add OP-TEE backend support
From: Arnaud Pouliquen @ 2026-04-14 15:29 UTC (permalink / raw)
  To: Bjorn Andersson, Mathieu Poirier, Jens Wiklander, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Sumit Garg
  Cc: linux-stm32, linux-arm-kernel, linux-remoteproc, linux-kernel,
	op-tee, devicetree, Arnaud Pouliquen
In-Reply-To: <20260414152904.1679724-1-arnaud.pouliquen@foss.st.com>

Integrate OP-TEE-controlled firmware loading into stm32_rproc
adding support for the st,rproc-tee devicetree property.

When st,rproc-tee is present, the driver:
- parses the backend phandle + ID from DT and validates it
- uses the remoteproc_tee operation set and registration path
- keeps reset/holdboot handling only for the non-TEE case
- uses a TEE-specific flow.

Notice that the attach/detach is not yet supported and should be part
of a separate patchset.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
---
V21 updates:
- reapply the V19 patch as the stm32_rproc-tee  driver can no more
  be used.
- update v19 patch to support the st,rproc-tee phandle.
- rework the commit message.
---
 drivers/remoteproc/stm32_rproc.c | 167 +++++++++++++++++++++++--------
 1 file changed, 123 insertions(+), 44 deletions(-)

diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c
index 4bcd6a784935..61d89f3a78b1 100644
--- a/drivers/remoteproc/stm32_rproc.c
+++ b/drivers/remoteproc/stm32_rproc.c
@@ -18,6 +18,7 @@
 #include <linux/pm_wakeirq.h>
 #include <linux/regmap.h>
 #include <linux/remoteproc.h>
+#include <linux/remoteproc_tee.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
@@ -89,6 +90,7 @@ struct stm32_rproc {
 	struct stm32_rproc_mem *rmems;
 	struct stm32_mbox mb[MBOX_NB_MBX];
 	struct workqueue_struct *workqueue;
+	struct of_phandle_args tee_phandle;
 	bool hold_boot_smc;
 	void __iomem *rsc_va;
 };
@@ -255,6 +257,19 @@ static int stm32_rproc_release(struct rproc *rproc)
 	return 0;
 }
 
+static int stm32_rproc_tee_stop(struct rproc *rproc)
+{
+	int err;
+
+	stm32_rproc_request_shutdown(rproc);
+
+	err = rproc_tee_stop(rproc);
+	if (err)
+		return err;
+
+	return stm32_rproc_release(rproc);
+}
+
 static int stm32_rproc_prepare(struct rproc *rproc)
 {
 	struct device *dev = rproc->dev.parent;
@@ -683,6 +698,17 @@ static const struct rproc_ops st_rproc_ops = {
 	.get_boot_addr	= rproc_elf_get_boot_addr,
 };
 
+static const struct rproc_ops st_rproc_tee_ops = {
+	.prepare	= stm32_rproc_prepare,
+	.start		= rproc_tee_start,
+	.stop		= stm32_rproc_tee_stop,
+	.kick		= stm32_rproc_kick,
+	.load		= rproc_tee_load_fw,
+	.parse_fw	= rproc_tee_parse_fw,
+	.find_loaded_rsc_table = rproc_tee_find_loaded_rsc_table,
+	.release_fw	= rproc_tee_release_fw,
+};
+
 static const struct of_device_id stm32_rproc_match[] = {
 	{ .compatible = "st,stm32mp1-m4" },
 	{},
@@ -716,6 +742,7 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev,
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
+	struct of_phandle_args tee_phandle;
 	struct stm32_syscon tz;
 	unsigned int tzen;
 	int err, irq;
@@ -741,51 +768,69 @@ static int stm32_rproc_parse_dt(struct platform_device *pdev,
 		dev_info(dev, "wdg irq registered\n");
 	}
 
-	ddata->rst = devm_reset_control_get_optional(dev, "mcu_rst");
-	if (!ddata->rst) {
-		/* Try legacy fallback method: get it by index */
-		ddata->rst = devm_reset_control_get_by_index(dev, 0);
+	if (of_find_property(np, "st,rproc-tee", NULL)) {
+		err = of_parse_phandle_with_fixed_args(np, "st,rproc-tee",
+						       1, 0, &tee_phandle);
+		if (err)
+			return dev_err_probe(dev, err,
+					     "failed to parse st,rproc-tee\n");
+
+		if (!IS_ENABLED(CONFIG_REMOTEPROC_TEE)) {
+			of_node_put(tee_phandle.np);
+			return dev_err_probe(dev, -ENODEV,
+					     "st,rproc-tee requires REMOTEPROC_TEE support\n");
+		}
+
+		ddata->tee_phandle = tee_phandle;
 	}
-	if (IS_ERR(ddata->rst))
-		return dev_err_probe(dev, PTR_ERR(ddata->rst),
-				     "failed to get mcu_reset\n");
 
-	/*
-	 * Three ways to manage the hold boot
-	 * - using SCMI: the hold boot is managed as a reset
-	 *    The DT "reset-mames" property should be defined with 2 items:
-	 *        reset-names = "mcu_rst", "hold_boot";
-	 * - using SMC call (deprecated): use SMC reset interface
-	 *    The DT "reset-mames" property is optional, "st,syscfg-tz" is required
-	 * - default(no SCMI, no SMC): the hold boot is managed as a syscon register
-	 *    The DT "reset-mames" property is optional, "st,syscfg-holdboot" is required
-	 */
+	if (!ddata->tee_phandle.np) {
+		ddata->rst = devm_reset_control_get_optional(dev, "mcu_rst");
+		if (!ddata->rst) {
+			/* Try legacy fallback method: get it by index */
+			ddata->rst = devm_reset_control_get_by_index(dev, 0);
+		}
+		if (IS_ERR(ddata->rst))
+			return dev_err_probe(dev, PTR_ERR(ddata->rst),
+					"failed to get mcu_reset\n");
 
-	ddata->hold_boot_rst = devm_reset_control_get_optional(dev, "hold_boot");
-	if (IS_ERR(ddata->hold_boot_rst))
-		return dev_err_probe(dev, PTR_ERR(ddata->hold_boot_rst),
-				     "failed to get hold_boot reset\n");
+		/*
+		 * Three ways to manage the hold boot
+		 * - using SCMI: the hold boot is managed as a reset
+		 *    The DT "reset-mames" property should be defined with 2 items:
+		 *        reset-names = "mcu_rst", "hold_boot";
+		 * - using SMC call (deprecated): use SMC reset interface
+		 *    The DT "reset-mames" property is optional, "st,syscfg-tz" is required
+		 * - default(no SCMI, no SMC): the hold boot is managed as a syscon register
+		 *    The DT "reset-mames" property is optional, "st,syscfg-holdboot" is required
+		 */
 
-	if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) {
-		/* Manage the MCU_BOOT using SMC call */
-		err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
-		if (!err) {
-			err = regmap_read(tz.map, tz.reg, &tzen);
-			if (err) {
-				dev_err(dev, "failed to read tzen\n");
-				return err;
+		ddata->hold_boot_rst = devm_reset_control_get_optional(dev, "hold_boot");
+		if (IS_ERR(ddata->hold_boot_rst))
+			return dev_err_probe(dev, PTR_ERR(ddata->hold_boot_rst),
+					"failed to get hold_boot reset\n");
+
+		if (!ddata->hold_boot_rst && IS_ENABLED(CONFIG_HAVE_ARM_SMCCC)) {
+			/* Manage the MCU_BOOT using SMC call */
+			err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz);
+			if (!err) {
+				err = regmap_read(tz.map, tz.reg, &tzen);
+				if (err) {
+					dev_err(dev, "failed to read tzen\n");
+					return err;
+				}
+				ddata->hold_boot_smc = tzen & tz.mask;
 			}
-			ddata->hold_boot_smc = tzen & tz.mask;
 		}
-	}
 
-	if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) {
-		/* Default: hold boot manage it through the syscon controller */
-		err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
-					     &ddata->hold_boot);
-		if (err) {
-			dev_err(dev, "failed to get hold boot\n");
-			return err;
+		if (!ddata->hold_boot_rst && !ddata->hold_boot_smc) {
+			/* Default: hold boot manage it through the syscon controller */
+			err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot",
+						     &ddata->hold_boot);
+			if (err) {
+				dev_err(dev, "failed to get hold boot\n");
+				return err;
+			}
 		}
 	}
 
@@ -857,18 +902,31 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 	if (ret < 0 && ret != -EINVAL)
 		return ret;
 
-	rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, fw_name, sizeof(*ddata));
+	if (of_find_property(np, "st,rproc-tee", NULL))
+		rproc = devm_rproc_alloc(dev, np->name, &st_rproc_tee_ops, fw_name,
+					 sizeof(*ddata));
+	else
+		rproc = devm_rproc_alloc(dev, np->name, &st_rproc_ops, fw_name,
+					 sizeof(*ddata));
+
 	if (!rproc)
 		return -ENOMEM;
 
 	ddata = rproc->priv;
-
 	rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
 
 	ret = stm32_rproc_parse_dt(pdev, ddata, &rproc->auto_boot);
 	if (ret)
 		goto free_rproc;
 
+	if (ddata->tee_phandle.np &&
+	    !of_device_is_available(ddata->tee_phandle.np)) {
+		of_node_put(ddata->tee_phandle.np);
+		ddata->tee_phandle.np = NULL;
+		ret = -EPROBE_DEFER;
+		goto free_rproc;
+	}
+
 	ret = stm32_rproc_of_memory_translations(pdev, ddata);
 	if (ret)
 		goto free_rproc;
@@ -877,8 +935,14 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_rproc;
 
-	if (state == M4_STATE_CRUN)
+	if (state == M4_STATE_CRUN) {
+		if (ddata->tee_phandle.np) {
+			dev_err(dev, "TEE support not yet compatible with attached state\n");
+			ret = -EINVAL;
+			goto free_rproc;
+		}
 		rproc->state = RPROC_DETACHED;
+	}
 
 	rproc->has_iommu = false;
 	ddata->workqueue = create_workqueue(dev_name(dev));
@@ -894,10 +958,12 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_wkq;
 
-	ret = rproc_add(rproc);
+	if (ddata->tee_phandle.np)
+		ret = rproc_tee_register(dev, rproc, &ddata->tee_phandle);
+	else
+		ret = rproc_add(rproc);
 	if (ret)
 		goto free_mb;
-
 	return 0;
 
 free_mb:
@@ -911,6 +977,11 @@ static int stm32_rproc_probe(struct platform_device *pdev)
 		dev_pm_clear_wake_irq(dev);
 		device_init_wakeup(dev, false);
 	}
+	if (ddata->tee_phandle.np) {
+		of_node_put(ddata->tee_phandle.np);
+		ddata->tee_phandle.np = NULL;
+	}
+
 	return ret;
 }
 
@@ -919,11 +990,11 @@ static void stm32_rproc_remove(struct platform_device *pdev)
 	struct rproc *rproc = platform_get_drvdata(pdev);
 	struct stm32_rproc *ddata = rproc->priv;
 	struct device *dev = &pdev->dev;
+	struct device_node *tee_np = ddata->tee_phandle.np;
 
 	if (atomic_read(&rproc->power) > 0)
 		rproc_shutdown(rproc);
 
-	rproc_del(rproc);
 	stm32_rproc_free_mbox(rproc);
 	destroy_workqueue(ddata->workqueue);
 
@@ -931,6 +1002,14 @@ static void stm32_rproc_remove(struct platform_device *pdev)
 		dev_pm_clear_wake_irq(dev);
 		device_init_wakeup(dev, false);
 	}
+
+	if (tee_np) {
+		ddata->tee_phandle.np = NULL;
+		rproc_tee_unregister(dev, rproc);
+		of_node_put(tee_np);
+	} else {
+		rproc_del(rproc);
+	}
 }
 
 static int stm32_rproc_suspend(struct device *dev)
-- 
2.43.0



^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox