Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/2] mailbox: Make mbox_send_message() return error code when tx fails
From: Joonwon Kang @ 2026-04-03 15:19 UTC (permalink / raw)
  To: jassisinghbrar
  Cc: angelogioacchino.delregno, jonathanh, joonwonkang,
	linux-arm-kernel, linux-kernel, linux-mediatek, linux-tegra,
	matthias.bgg, stable, thierry.reding, akpm
In-Reply-To: <CABb+yY3hYcJ82QGor3w5KKHUGz9Pc1k64Jdf-94E4Yvv0DTeyQ@mail.gmail.com>

> On Thu, Apr 2, 2026 at 12:07 PM Joonwon Kang <joonwonkang@google.com> wrote:
> >
> > When the mailbox controller failed transmitting message, the error code
> > was only passed to the client's tx done handler and not to
> > mbox_send_message(). For this reason, the function could return a false
> > success. This commit resolves the issue by introducing the tx status and
> > checking it before mbox_send_message() returns.
> >
> Can you please share the scenario when this becomes necessary? This
> can potentially change the ground underneath some clients, so we have
> to be sure this is really useful.

I would say the problem here is generic enough to apply to all the cases where
the send result needs to be checked. Since the return value of the send API is
not the real send result, any users who believe that this blocking send API
will return the real send result could fall for that. For example, users may
think the send was successful even though it was not actually. I believe it is
uncommon that users have to register a callback solely to get the send result
even though they are using the blocking send API already. Also, I guess there
is no special reason why only the mailbox send API should work this way among
other typical blocking send APIs. For these reasons, this patch makes the send
API return the real send result. This way, users will not need to register the
redundant callback and I think the return value will align with their common
expectation.

Regarding the change in the ground for some clients, could you help to clarify
a bit more on what change, you expect, would surprise the clients?

Thanks,
Joonwon Kang

> 
> Thanks
> Jassi
> 
> 
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Joonwon Kang <joonwonkang@google.com>
> > ---
> >  drivers/mailbox/mailbox.c          | 20 +++++++++++++++-----
> >  include/linux/mailbox_controller.h |  2 ++
> >  2 files changed, 17 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
> > index d63386468982..ea9aec9dc947 100644
> > --- a/drivers/mailbox/mailbox.c
> > +++ b/drivers/mailbox/mailbox.c
> > @@ -21,7 +21,10 @@
> >  static LIST_HEAD(mbox_cons);
> >  static DEFINE_MUTEX(con_mutex);
> >
> > -static int add_to_rbuf(struct mbox_chan *chan, void *mssg, struct completion *tx_complete)
> > +static int add_to_rbuf(struct mbox_chan *chan,
> > +                      void *mssg,
> > +                      struct completion *tx_complete,
> > +                      int *tx_status)
> >  {
> >         int idx;
> >
> > @@ -34,6 +37,7 @@ static int add_to_rbuf(struct mbox_chan *chan, void *mssg, struct completion *tx
> >         idx = chan->msg_free;
> >         chan->msg_data[idx].data = mssg;
> >         chan->msg_data[idx].tx_complete = tx_complete;
> > +       chan->msg_data[idx].tx_status = tx_status;
> >         chan->msg_count++;
> >
> >         if (idx == MBOX_TX_QUEUE_LEN - 1)
> > @@ -91,12 +95,13 @@ static void msg_submit(struct mbox_chan *chan)
> >
> >  static void tx_tick(struct mbox_chan *chan, int r, int idx)
> >  {
> > -       struct mbox_message mssg = {MBOX_NO_MSG, NULL};
> > +       struct mbox_message mssg = {MBOX_NO_MSG, NULL, NULL};
> >
> >         scoped_guard(spinlock_irqsave, &chan->lock) {
> >                 if (idx >= 0 && idx != chan->active_req) {
> >                         chan->msg_data[idx].data = MBOX_NO_MSG;
> >                         chan->msg_data[idx].tx_complete = NULL;
> > +                       chan->msg_data[idx].tx_status = NULL;
> >                         return;
> >                 }
> >
> > @@ -116,8 +121,10 @@ static void tx_tick(struct mbox_chan *chan, int r, int idx)
> >         if (chan->cl->tx_done)
> >                 chan->cl->tx_done(chan->cl, mssg.data, r);
> >
> > -       if (r != -ETIME && chan->cl->tx_block)
> > +       if (r != -ETIME && chan->cl->tx_block) {
> > +               *mssg.tx_status = r;
> >                 complete(mssg.tx_complete);
> > +       }
> >  }
> >
> >  static enum hrtimer_restart txdone_hrtimer(struct hrtimer *hrtimer)
> > @@ -286,15 +293,16 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
> >         int t;
> >         int idx;
> >         struct completion tx_complete;
> > +       int tx_status = 0;
> >
> >         if (!chan || !chan->cl || mssg == MBOX_NO_MSG)
> >                 return -EINVAL;
> >
> >         if (chan->cl->tx_block) {
> >                 init_completion(&tx_complete);
> > -               t = add_to_rbuf(chan, mssg, &tx_complete);
> > +               t = add_to_rbuf(chan, mssg, &tx_complete, &tx_status);
> >         } else {
> > -               t = add_to_rbuf(chan, mssg, NULL);
> > +               t = add_to_rbuf(chan, mssg, NULL, NULL);
> >         }
> >
> >         if (t < 0) {
> > @@ -318,6 +326,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
> >                         idx = t;
> >                         t = -ETIME;
> >                         tx_tick(chan, t, idx);
> > +               } else if (tx_status < 0) {
> > +                       t = tx_status;
> >                 }
> >         }
> >
> > diff --git a/include/linux/mailbox_controller.h b/include/linux/mailbox_controller.h
> > index 912499ad08ed..890da97bcb50 100644
> > --- a/include/linux/mailbox_controller.h
> > +++ b/include/linux/mailbox_controller.h
> > @@ -117,10 +117,12 @@ struct mbox_controller {
> >   * struct mbox_message - Internal representation of a mailbox message
> >   * @data:              Data packet
> >   * @tx_complete:       Pointer to the transmission completion
> > + * @tx_status:         Pointer to the transmission status
> >   */
> >  struct mbox_message {
> >         void *data;
> >         struct completion *tx_complete;
> > +       int *tx_status;
> >  };
> >
> >  /**
> > --
> > 2.53.0.1185.g05d4b7b318-goog
> >


^ permalink raw reply

* Re: [PATCH v6 08/10] clk: realtek: Add RTD1625-CRT clock controller driver
From: Brian Masney @ 2026-04-03 15:24 UTC (permalink / raw)
  To: Yu-Chun Lin
  Cc: mturquette, sboyd, robh, krzk+dt, conor+dt, p.zabel, cylee12,
	afaerber, jyanchou, devicetree, linux-clk, linux-kernel,
	linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
	stanley_chang
In-Reply-To: <20260402073957.2742459-9-eleanor.lin@realtek.com>

Hi Yu-Chun,

On Thu, Apr 02, 2026 at 03:39:55PM +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Add support for the CRT (Clock, Reset, and Test) domain clock controller
> on the Realtek RTD1625 SoC. This driver provides essential clock sources
> (including PLLs), gating, and multiplexing functionalities for the
> platform's peripherals.
> 
> Since the reset controller shares the same register space with the CRT
> clock controller, it is instantiated as an auxiliary device by the core
> clock driver. This patch also includes the corresponding auxiliary reset
> driver to handle the CRT domain resets.
> 
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v6:
> - Add the headers used in c file to follow the "Include What You Use" principle.
> - Move struct rtk_reset_desc array from the clock driver to the dedicated reset driver.
> - Implement and register a dedicated reset auxiliary driver.
> ---
>  drivers/clk/realtek/Kconfig               |  13 +
>  drivers/clk/realtek/Makefile              |   1 +
>  drivers/clk/realtek/clk-rtd1625-crt.c     | 779 ++++++++++++++++++++++
>  drivers/reset/realtek/Kconfig             |   2 +
>  drivers/reset/realtek/Makefile            |   2 +-
>  drivers/reset/realtek/reset-rtd1625-crt.c | 186 ++++++
>  6 files changed, 982 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/realtek/clk-rtd1625-crt.c
>  create mode 100644 drivers/reset/realtek/reset-rtd1625-crt.c
> 
> diff --git a/drivers/clk/realtek/Kconfig b/drivers/clk/realtek/Kconfig
> index b31a31e57b3a..6a213cfd66bc 100644
> --- a/drivers/clk/realtek/Kconfig
> +++ b/drivers/clk/realtek/Kconfig
> @@ -28,4 +28,17 @@ config RTK_CLK_COMMON
>  config RTK_CLK_PLL_MMC
>  	bool
>  
> +config COMMON_CLK_RTD1625
> +	tristate "RTD1625 Clock Controller"
> +	select RTK_CLK_COMMON
> +	select RTK_CLK_PLL_MMC
> +	help
> +	  Support for the clock controller on Realtek RTD1625 SoCs.
> +
> +	  This driver provides clock sources, gating, multiplexing, and
> +	  reset control for peripherals on the RTD1625 platform.
> +
> +	  Say Y here if your system is based on the RTD1625 and you need
> +	  its peripheral devices to function.
> +
>  endif
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index fd7d777902c8..c992f97dfbc7 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -9,3 +9,4 @@ clk-rtk-y += clk-regmap-mux.o
>  clk-rtk-y += freq_table.o
>  
>  clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-pll-mmc.o
> +obj-$(CONFIG_COMMON_CLK_RTD1625) += clk-rtd1625-crt.o
> diff --git a/drivers/clk/realtek/clk-rtd1625-crt.c b/drivers/clk/realtek/clk-rtd1625-crt.c
> new file mode 100644
> index 000000000000..fcb8b08722c8
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtd1625-crt.c
> @@ -0,0 +1,779 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2022 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <dt-bindings/clock/realtek,rtd1625-clk.h>
> +#include <linux/array_size.h>
> +#include <linux/bits.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include "clk-pll.h"
> +#include "clk-regmap-gate.h"
> +#include "clk-regmap-mux.h"
> +
> +#define RTD1625_CRT_CLK_MAX	172
> +#define RTD1625_CRT_RSTN_MAX	123
> +
> +#define RTD1625_REG_PLL_ACPU1			0x10c
> +#define RTD1625_REG_PLL_ACPU2			0x110
> +#define RTD1625_REG_PLL_SSC_DIG_ACPU0		0x5c0
> +#define RTD1625_REG_PLL_SSC_DIG_ACPU1		0x5c4
> +#define RTD1625_REG_PLL_SSC_DIG_ACPU2		0x5c8
> +#define RTD1625_REG_PLL_SSC_DIG_ACPU_DBG2	0x5dc
> +
> +#define RTD1625_REG_PLL_VE1_1			0x114
> +#define RTD1625_REG_PLL_VE1_2			0x118
> +#define RTD1625_REG_PLL_SSC_DIG_VE1_0		0x580
> +#define RTD1625_REG_PLL_SSC_DIG_VE1_1		0x584
> +#define RTD1625_REG_PLL_SSC_DIG_VE1_2		0x588
> +#define RTD1625_REG_PLL_SSC_DIG_VE1_DBG2	0x59c
> +
> +#define RTD1625_REG_PLL_GPU1			0x1c0
> +#define RTD1625_REG_PLL_GPU2			0x1c4
> +#define RTD1625_REG_PLL_SSC_DIG_GPU0		0x5a0
> +#define RTD1625_REG_PLL_SSC_DIG_GPU1		0x5a4
> +#define RTD1625_REG_PLL_SSC_DIG_GPU2		0x5a8
> +#define RTD1625_REG_PLL_SSC_DIG_GPU_DBG2	0x5bc
> +
> +#define RTD1625_REG_PLL_NPU1			0x1c8
> +#define RTD1625_REG_PLL_NPU2			0x1cc
> +#define RTD1625_REG_PLL_SSC_DIG_NPU0		0x800
> +#define RTD1625_REG_PLL_SSC_DIG_NPU1		0x804
> +#define RTD1625_REG_PLL_SSC_DIG_NPU2		0x808
> +#define RTD1625_REG_PLL_SSC_DIG_NPU_DBG2	0x81c
> +
> +#define RTD1625_REG_PLL_VE2_1			0x1d0
> +#define RTD1625_REG_PLL_VE2_2			0x1d4
> +#define RTD1625_REG_PLL_SSC_DIG_VE2_0		0x5e0
> +#define RTD1625_REG_PLL_SSC_DIG_VE2_1		0x5e4
> +#define RTD1625_REG_PLL_SSC_DIG_VE2_2		0x5e8
> +#define RTD1625_REG_PLL_SSC_DIG_VE2_DBG2	0x5fc
> +
> +#define RTD1625_REG_PLL_HIFI1			0x1d8
> +#define RTD1625_REG_PLL_HIFI2			0x1dc
> +#define RTD1625_REG_PLL_SSC_DIG_HIFI0		0x6e0
> +#define RTD1625_REG_PLL_SSC_DIG_HIFI1		0x6e4
> +#define RTD1625_REG_PLL_SSC_DIG_HIFI2		0x6e8
> +#define RTD1625_REG_PLL_SSC_DIG_HIFI_DBG2	0x6fc
> +
> +#define RTD1625_REG_PLL_BUS1	0x524
> +
> +#define RTD1625_REG_PLL_SSC_DIG_DDSA1	0x564
> +
> +#define RTD1625_REG_PLL_SSC_DIG_DCSB1	0x544
> +
> +static const char * const clk_gpu_parents[] = {"pll_gpu", "clk_sys"};
> +static CLK_REGMAP_MUX(clk_gpu, clk_gpu_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> +		      0x28, 12, 0x1);
> +static const char * const clk_ve_parents[] = {"pll_vo", "clk_sysh", "pll_ve1", "pll_ve2"};
> +static CLK_REGMAP_MUX(clk_ve1, clk_ve_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> +		      0x4c, 0, 0x3);
> +static CLK_REGMAP_MUX(clk_ve2, clk_ve_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> +		      0x4c, 3, 0x3);
> +static CLK_REGMAP_MUX(clk_ve4, clk_ve_parents, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
> +		      0x4c, 6, 0x3);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_misc, CLK_IS_CRITICAL, 0x50, 0, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_pcie0, 0, 0x50, 2, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_gspi, 0, 0x50, 6, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_iso_misc, 0, 0x50, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sds, 0, 0x50, 12, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_hdmi, 0, 0x50, 14, 1);
> +static CLK_REGMAP_GATE(clk_en_gpu, "clk_gpu", CLK_SET_RATE_PARENT, 0x50, 18, 1);
> +static CLK_REGMAP_GATE(clk_en_ve1, "clk_ve1", CLK_SET_RATE_PARENT, 0x50, 20, 1);
> +static CLK_REGMAP_GATE(clk_en_ve2, "clk_ve2", CLK_SET_RATE_PARENT, 0x50, 22, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_se, 0, 0x50, 30, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_md, 0, 0x54, 4, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_tp, CLK_IS_CRITICAL, 0x54, 6, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_rcic, 0, 0x54, 8, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_nf, 0, 0x54, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_emmc, 0, 0x54, 12, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sd, 0, 0x54, 14, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sdio_ip, 0, 0x54, 16, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mipi_csi, 0, 0x54, 18, 1);
> +static CLK_REGMAP_GATE(clk_en_emmc_ip, "pll_emmc", CLK_SET_RATE_PARENT, 0x54, 20, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sdio, 0, 0x54, 22, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sd_ip, 0, 0x54, 24, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_tpb, 0, 0x54, 28, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_sc1, "clk_en_misc", 0, 0x54, 30, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_i2c_3, "clk_en_misc", 0, 0x58, 0, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_jpeg, 0, 0x58, 4, 1);
> +static CLK_REGMAP_GATE(clk_en_acpu, "pll_acpu", CLK_SET_RATE_PARENT,
> +		       0x58, 6, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_sc0, "clk_en_misc", 0, 0x58, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_hdmirx, 0, 0x58, 26, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_hse, CLK_IS_CRITICAL, 0x58, 28, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_fan, 0, 0x5c, 2, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sata_wrap_sys, 0, 0x5c, 8, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sata_wrap_sysh, 0, 0x5c, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_sata_mac_sysh, 0, 0x5c, 12, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_r2rdsc, 0, 0x5c, 14, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_pcie1, 0, 0x5c, 18, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_i2c_4, "clk_en_misc", 0, 0x5c, 20, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_i2c_5, "clk_en_misc", 0, 0x5c, 22, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_tsio, 0, 0x5c, 24, 1);
> +static CLK_REGMAP_GATE(clk_en_ve4, "clk_ve4", CLK_SET_RATE_PARENT,
> +		       0x5c, 26, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_edp, 0, 0x5c, 28, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_tsio_trx, 0, 0x5c, 30, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_pcie2, 0, 0x8c, 0, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_earc, 0, 0x8c, 4, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_lite, 0, 0x8c, 6, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mipi_dsi, 0, 0x8c, 8, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_npupp, 0, 0x8c, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_npu, 0, 0x8c, 12, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_aucpu0, 0, 0x8c, 14, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_aucpu1, 0, 0x8c, 16, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_nsram, 0, 0x8c, 18, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_hdmitop, 0, 0x8c, 20, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_aucpu_iso_npu, 0, 0x8c, 24, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_keyladder, 0, 0x8c, 26, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_ifcp_klm, 0, 0x8c, 28, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_ifcp, 0, 0x8c, 30, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mdl_genpw, 0, 0xb0, 0, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mdl_chip, 0, 0xb0, 2, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mdl_ip, 0, 0xb0, 4, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mdlm2m, 0, 0xb0, 6, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_mdl_xtal, 0, 0xb0, 8, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_test_mux, 0, 0xb0, 10, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_dla, 0, 0xb0, 12, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_tpcw, 0, 0xb0, 16, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_gpu_ts_src, 0, 0xb0, 18, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_vi, 0, 0xb0, 22, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_lvds1, 0, 0xb0, 24, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_lvds2, 0, 0xb0, 26, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_aucpu, 0, 0xb0, 28, 1);
> +static CLK_REGMAP_GATE(clk_en_ur1, "clk_en_ur_top", 0, 0x884, 0, 1);
> +static CLK_REGMAP_GATE(clk_en_ur2, "clk_en_ur_top", 0, 0x884, 2, 1);
> +static CLK_REGMAP_GATE(clk_en_ur3, "clk_en_ur_top", 0, 0x884, 4, 1);
> +static CLK_REGMAP_GATE(clk_en_ur4, "clk_en_ur_top", 0, 0x884, 6, 1);
> +static CLK_REGMAP_GATE(clk_en_ur5, "clk_en_ur_top", 0, 0x884, 8, 1);
> +static CLK_REGMAP_GATE(clk_en_ur6, "clk_en_ur_top", 0, 0x884, 10, 1);
> +static CLK_REGMAP_GATE(clk_en_ur7, "clk_en_ur_top", 0, 0x884, 12, 1);
> +static CLK_REGMAP_GATE(clk_en_ur8, "clk_en_ur_top", 0, 0x884, 14, 1);
> +static CLK_REGMAP_GATE(clk_en_ur9, "clk_en_ur_top", 0, 0x884, 16, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_ur_top, CLK_IS_CRITICAL, 0x884, 18, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_i2c_7, "clk_en_misc", 0, 0x884, 28, 1);
> +static CLK_REGMAP_GATE(clk_en_misc_i2c_6, "clk_en_misc", 0, 0x884, 30, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_spi0, 0, 0x894, 0, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_spi1, 0, 0x894, 2, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_spi2, 0, 0x894, 4, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_lsadc0, 0, 0x894, 16, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_lsadc1, 0, 0x894, 18, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_isomis_dma, 0, 0x894, 20, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_dptx, 0, 0x894, 24, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_npu_mipi_csi, 0, 0x894, 26, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_edptx, 0, 0x894, 28, 1);
> +
> +#define FREQ_NF_MASK       0x7ffff
> +#define FREQ_NF(_r, _nf)   {.rate = _r, .val = (_nf),}
> +
> +static const struct freq_table acpu_tbl[] = {
> +	FREQ_NF(513000000, 0x11000),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table ve_tbl[] = {
> +	FREQ_NF(553500000, 0x12800),
> +	FREQ_NF(661500000, 0x16800),
> +	FREQ_NF(688500000, 0x17800),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table bus_tbl[] = {
> +	FREQ_NF(513000000, 0x11000),
> +	FREQ_NF(540000000, 0x12000),
> +	FREQ_NF(553500000, 0x12800),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table ddsa_tbl[] = {
> +	FREQ_NF(432000000, 0xe000),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table gpu_tbl[] = {
> +	FREQ_NF(405000000, 0xd000),
> +	FREQ_NF(540000000, 0x12000),
> +	FREQ_NF(661500000, 0x16800),
> +	FREQ_NF(729000000, 0x19000),
> +	FREQ_NF(810000000, 0x1c000),
> +	FREQ_NF(850500000, 0x1d800),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table hifi_tbl[] = {
> +	FREQ_NF(756000000, 0x1a000),
> +	FREQ_NF(810000000, 0x1c000),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct freq_table npu_tbl[] = {
> +	FREQ_NF(661500000, 0x16800),
> +	FREQ_NF(729000000, 0x19000),
> +	FREQ_NF(810000000, 0x1c000),
> +	FREQ_TABLE_END
> +};
> +
> +static const struct reg_sequence pll_acpu_seq_power_on[] = {
> +	{RTD1625_REG_PLL_ACPU2,         0x5},
> +	{RTD1625_REG_PLL_ACPU2,         0x7},
> +	{RTD1625_REG_PLL_ACPU1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_ACPU2, 0x1e1f8e},
> +	{RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x5, 200},
> +	{RTD1625_REG_PLL_ACPU2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_acpu_seq_power_off[] = {
> +	{RTD1625_REG_PLL_ACPU2,         0x4},
> +};
> +
> +static const struct reg_sequence pll_acpu_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_acpu_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_ACPU0, 0x5},
> +};
> +
> +static struct clk_pll pll_acpu = {

static const?

> +	.clkr.hw.init = CLK_HW_INIT("pll_acpu", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_acpu_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_acpu_seq_power_on),
> +	.seq_power_off         = pll_acpu_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_acpu_seq_power_off),
> +	.seq_pre_set_freq      = pll_acpu_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_acpu_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_acpu_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_acpu_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_ACPU1,
> +	.freq_tbl              = acpu_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_ACPU_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_ACPU2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static const struct reg_sequence pll_ve1_seq_power_on[] = {
> +	{RTD1625_REG_PLL_VE1_2,         0x5},
> +	{RTD1625_REG_PLL_VE1_2,         0x7},
> +	{RTD1625_REG_PLL_VE1_1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x5, 200},
> +	{RTD1625_REG_PLL_VE1_2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_ve1_seq_power_off[] = {
> +	{RTD1625_REG_PLL_VE1_2,         0x4},
> +};
> +
> +static const struct reg_sequence pll_ve1_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_ve1_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_VE1_0, 0x5},
> +};
> +
> +static struct clk_pll pll_ve1 = {

Same here about static const, plus some others below?

> +	.clkr.hw.init = CLK_HW_INIT("pll_ve1", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_ve1_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_ve1_seq_power_on),
> +	.seq_power_off         = pll_ve1_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_ve1_seq_power_off),
> +	.seq_pre_set_freq      = pll_ve1_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_ve1_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_ve1_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_ve1_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_VE1_1,
> +	.freq_tbl              = ve_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_VE1_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_VE1_2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static struct clk_pll pll_ddsa = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_ddsa", "osc27m", &rtk_clk_pll_ro_ops,
> +				    CLK_GET_RATE_NOCACHE),
> +	.freq_reg     = RTD1625_REG_PLL_SSC_DIG_DDSA1,
> +	.freq_tbl     = ddsa_tbl,
> +	.freq_mask    = FREQ_NF_MASK,
> +};
> +
> +static struct clk_pll pll_bus = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_bus", "osc27m", &rtk_clk_pll_ro_ops, CLK_GET_RATE_NOCACHE),
> +	.freq_reg     = RTD1625_REG_PLL_BUS1,
> +	.freq_tbl     = bus_tbl,
> +	.freq_mask    = FREQ_NF_MASK,
> +};
> +
> +static CLK_FIXED_FACTOR(clk_sys, "clk_sys", "pll_bus", 2, 1, 0);
> +
> +static struct clk_pll pll_dcsb = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_dcsb", "osc27m", &rtk_clk_pll_ro_ops,
> +				    CLK_GET_RATE_NOCACHE),
> +	.freq_reg     = RTD1625_REG_PLL_SSC_DIG_DCSB1,
> +	.freq_tbl     = bus_tbl,
> +	.freq_mask    = FREQ_NF_MASK,
> +};
> +
> +static CLK_FIXED_FACTOR(clk_sysh, "clk_sysh", "pll_dcsb", 1, 1, 0);
> +
> +static const struct reg_sequence pll_gpu_seq_power_on[] = {
> +	{RTD1625_REG_PLL_GPU2,         0x5},
> +	{RTD1625_REG_PLL_GPU2,         0x7},
> +	{RTD1625_REG_PLL_GPU1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_GPU0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_GPU0, 0x5, 200},
> +	{RTD1625_REG_PLL_GPU2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_gpu_seq_power_off[] = {
> +	{RTD1625_REG_PLL_GPU2,         0x4},
> +};
> +
> +static const struct reg_sequence pll_gpu_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_GPU0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_gpu_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_GPU0, 0x5},
> +};
> +
> +static struct clk_pll pll_gpu = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_gpu", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_gpu_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_gpu_seq_power_on),
> +	.seq_power_off         = pll_gpu_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_gpu_seq_power_off),
> +	.seq_pre_set_freq      = pll_gpu_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_gpu_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_gpu_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_gpu_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_GPU1,
> +	.freq_tbl              = gpu_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_GPU_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_GPU2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static const struct reg_sequence pll_npu_seq_power_on[] = {
> +	{RTD1625_REG_PLL_NPU2,         0x5},
> +	{RTD1625_REG_PLL_NPU2,         0x7},
> +	{RTD1625_REG_PLL_NPU1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_NPU0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_NPU0, 0x5, 200},
> +	{RTD1625_REG_PLL_NPU2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_npu_seq_power_off[] = {
> +	{RTD1625_REG_PLL_NPU2,         0x4},
> +	{RTD1625_REG_PLL_NPU1,         0x54010},
> +};
> +
> +static const struct reg_sequence pll_npu_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_NPU0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_npu_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_NPU0, 0x5},
> +};
> +
> +static struct clk_pll pll_npu = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_npu", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_npu_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_npu_seq_power_on),
> +	.seq_power_off         = pll_npu_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_npu_seq_power_off),
> +	.seq_pre_set_freq      = pll_npu_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_npu_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_npu_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_npu_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_NPU1,
> +	.freq_tbl              = npu_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_NPU_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_NPU2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static CLK_FIXED_FACTOR(clk_npu, "clk_npu", "pll_npu", 1, 1, CLK_SET_RATE_PARENT);
> +static CLK_FIXED_FACTOR(clk_npu_mipi_csi, "clk_npu_mipi_csi", "pll_npu", 1, 1,
> +			CLK_SET_RATE_PARENT);
> +
> +static const struct reg_sequence pll_ve2_seq_power_on[] = {
> +	{RTD1625_REG_PLL_VE2_2,         0x5},
> +	{RTD1625_REG_PLL_VE2_2,         0x7},
> +	{RTD1625_REG_PLL_VE2_1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x5, 200},
> +	{RTD1625_REG_PLL_VE2_2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_ve2_seq_power_off[] = {
> +	{RTD1625_REG_PLL_VE2_2,         0x4},
> +};
> +
> +static const struct reg_sequence pll_ve2_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_ve2_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_VE2_0, 0x5},
> +};
> +
> +static struct clk_pll pll_ve2 = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_ve2", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_ve2_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_ve2_seq_power_on),
> +	.seq_power_off         = pll_ve2_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_ve2_seq_power_off),
> +	.seq_pre_set_freq      = pll_ve2_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_ve2_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_ve2_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_ve2_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_VE2_1,
> +	.freq_tbl              = ve_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_VE2_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_VE2_2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static const struct reg_sequence pll_hifi_seq_power_on[] = {
> +	{RTD1625_REG_PLL_HIFI2,         0x5},
> +	{RTD1625_REG_PLL_HIFI2,         0x7},
> +	{RTD1625_REG_PLL_HIFI1,         0x54000},
> +	{RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x4},
> +	{RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x5, 200},
> +	{RTD1625_REG_PLL_HIFI2,         0x3},
> +};
> +
> +static const struct reg_sequence pll_hifi_seq_power_off[] = {
> +	{RTD1625_REG_PLL_HIFI2,         0x4},
> +};
> +
> +static const struct reg_sequence pll_hifi_seq_pre_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x4},
> +};
> +
> +static const struct reg_sequence pll_hifi_seq_post_set_freq[] = {
> +	{RTD1625_REG_PLL_SSC_DIG_HIFI0, 0x5},
> +};
> +
> +static struct clk_pll pll_hifi = {
> +	.clkr.hw.init = CLK_HW_INIT("pll_hifi", "osc27m", &rtk_clk_pll_ops, CLK_GET_RATE_NOCACHE),
> +	.seq_power_on          = pll_hifi_seq_power_on,
> +	.num_seq_power_on      = ARRAY_SIZE(pll_hifi_seq_power_on),
> +	.seq_power_off         = pll_hifi_seq_power_off,
> +	.num_seq_power_off     = ARRAY_SIZE(pll_hifi_seq_power_off),
> +	.seq_pre_set_freq      = pll_hifi_seq_pre_set_freq,
> +	.num_seq_pre_set_freq  = ARRAY_SIZE(pll_hifi_seq_pre_set_freq),
> +	.seq_post_set_freq     = pll_hifi_seq_post_set_freq,
> +	.num_seq_post_set_freq = ARRAY_SIZE(pll_hifi_seq_post_set_freq),
> +	.freq_reg              = RTD1625_REG_PLL_SSC_DIG_HIFI1,
> +	.freq_tbl              = hifi_tbl,
> +	.freq_mask             = FREQ_NF_MASK,
> +	.freq_ready_reg        = RTD1625_REG_PLL_SSC_DIG_HIFI_DBG2,
> +	.freq_ready_mask       = BIT(20),
> +	.freq_ready_val        = BIT(20),
> +	.power_reg             = RTD1625_REG_PLL_HIFI2,
> +	.power_mask            = 0x7,
> +	.power_val_on          = 0x3,
> +};
> +
> +static CLK_FIXED_FACTOR(pll_emmc_ref, "pll_emmc_ref", "osc27m", 1, 1, 0);
> +
> +static struct clk_pll_mmc pll_emmc = {
> +	.pll_ofs        = 0x1f0,
> +	.ssc_dig_ofs    = 0x6b0,
> +	.clkr.hw.init   = CLK_HW_INIT("pll_emmc", "pll_emmc_ref", &rtk_clk_pll_mmc_ops, 0),
> +	.phase0_hw.init = CLK_HW_INIT("pll_emmc_vp0", "pll_emmc", &rtk_clk_pll_mmc_phase_ops, 0),
> +	.phase1_hw.init = CLK_HW_INIT("pll_emmc_vp1", "pll_emmc", &rtk_clk_pll_mmc_phase_ops, 0),
> +};
> +
> +static struct clk_regmap *rtd1625_crt_regmap_clks[] = {
> +	&clk_en_misc.clkr,
> +	&clk_en_pcie0.clkr,
> +	&clk_en_gspi.clkr,
> +	&clk_en_iso_misc.clkr,
> +	&clk_en_sds.clkr,
> +	&clk_en_hdmi.clkr,
> +	&clk_en_gpu.clkr,
> +	&clk_en_ve1.clkr,
> +	&clk_en_ve2.clkr,
> +	&clk_en_se.clkr,
> +	&clk_en_md.clkr,
> +	&clk_en_tp.clkr,
> +	&clk_en_rcic.clkr,
> +	&clk_en_nf.clkr,
> +	&clk_en_emmc.clkr,
> +	&clk_en_sd.clkr,
> +	&clk_en_sdio_ip.clkr,
> +	&clk_en_mipi_csi.clkr,
> +	&clk_en_emmc_ip.clkr,
> +	&clk_en_sdio.clkr,
> +	&clk_en_sd_ip.clkr,
> +	&clk_en_tpb.clkr,
> +	&clk_en_misc_sc1.clkr,
> +	&clk_en_misc_i2c_3.clkr,
> +	&clk_en_jpeg.clkr,
> +	&clk_en_acpu.clkr,
> +	&clk_en_misc_sc0.clkr,
> +	&clk_en_hdmirx.clkr,
> +	&clk_en_hse.clkr,
> +	&clk_en_fan.clkr,
> +	&clk_en_sata_wrap_sys.clkr,
> +	&clk_en_sata_wrap_sysh.clkr,
> +	&clk_en_sata_mac_sysh.clkr,
> +	&clk_en_r2rdsc.clkr,
> +	&clk_en_pcie1.clkr,
> +	&clk_en_misc_i2c_4.clkr,
> +	&clk_en_misc_i2c_5.clkr,
> +	&clk_en_tsio.clkr,
> +	&clk_en_ve4.clkr,
> +	&clk_en_edp.clkr,
> +	&clk_en_tsio_trx.clkr,
> +	&clk_en_pcie2.clkr,
> +	&clk_en_earc.clkr,
> +	&clk_en_lite.clkr,
> +	&clk_en_mipi_dsi.clkr,
> +	&clk_en_npupp.clkr,
> +	&clk_en_npu.clkr,
> +	&clk_en_aucpu0.clkr,
> +	&clk_en_aucpu1.clkr,
> +	&clk_en_nsram.clkr,
> +	&clk_en_hdmitop.clkr,
> +	&clk_en_aucpu_iso_npu.clkr,
> +	&clk_en_keyladder.clkr,
> +	&clk_en_ifcp_klm.clkr,
> +	&clk_en_ifcp.clkr,
> +	&clk_en_mdl_genpw.clkr,
> +	&clk_en_mdl_chip.clkr,
> +	&clk_en_mdl_ip.clkr,
> +	&clk_en_mdlm2m.clkr,
> +	&clk_en_mdl_xtal.clkr,
> +	&clk_en_test_mux.clkr,
> +	&clk_en_dla.clkr,
> +	&clk_en_tpcw.clkr,
> +	&clk_en_gpu_ts_src.clkr,
> +	&clk_en_vi.clkr,
> +	&clk_en_lvds1.clkr,
> +	&clk_en_lvds2.clkr,
> +	&clk_en_aucpu.clkr,
> +	&clk_en_ur1.clkr,
> +	&clk_en_ur2.clkr,
> +	&clk_en_ur3.clkr,
> +	&clk_en_ur4.clkr,
> +	&clk_en_ur5.clkr,
> +	&clk_en_ur6.clkr,
> +	&clk_en_ur7.clkr,
> +	&clk_en_ur8.clkr,
> +	&clk_en_ur9.clkr,
> +	&clk_en_ur_top.clkr,
> +	&clk_en_misc_i2c_7.clkr,
> +	&clk_en_misc_i2c_6.clkr,
> +	&clk_en_spi0.clkr,
> +	&clk_en_spi1.clkr,
> +	&clk_en_spi2.clkr,
> +	&clk_en_lsadc0.clkr,
> +	&clk_en_lsadc1.clkr,
> +	&clk_en_isomis_dma.clkr,
> +	&clk_en_dptx.clkr,
> +	&clk_en_npu_mipi_csi.clkr,
> +	&clk_en_edptx.clkr,
> +	&clk_gpu.clkr,
> +	&clk_ve1.clkr,
> +	&clk_ve2.clkr,
> +	&clk_ve4.clkr,
> +	&pll_ve1.clkr,
> +	&pll_ddsa.clkr,
> +	&pll_bus.clkr,
> +	&pll_dcsb.clkr,
> +	&pll_gpu.clkr,
> +	&pll_npu.clkr,
> +	&pll_ve2.clkr,
> +	&pll_hifi.clkr,
> +	&pll_emmc.clkr,
> +	&pll_acpu.clkr,
> +};
> +
> +static struct clk_hw_onecell_data rtd1625_crt_hw_data = {
> +	.num = RTD1625_CRT_CLK_MAX,
> +	.hws = {
> +		[RTD1625_CRT_CLK_EN_MISC]     = &__clk_regmap_gate_hw(&clk_en_misc),
> +		[RTD1625_CRT_CLK_EN_PCIE0]    = &__clk_regmap_gate_hw(&clk_en_pcie0),
> +		[RTD1625_CRT_CLK_EN_GSPI]     = &__clk_regmap_gate_hw(&clk_en_gspi),
> +		[RTD1625_CRT_CLK_EN_ISO_MISC] = &__clk_regmap_gate_hw(&clk_en_iso_misc),
> +		[RTD1625_CRT_CLK_EN_SDS]      = &__clk_regmap_gate_hw(&clk_en_sds),
> +		[RTD1625_CRT_CLK_EN_HDMI]     = &__clk_regmap_gate_hw(&clk_en_hdmi),
> +		[RTD1625_CRT_CLK_EN_GPU]      = &__clk_regmap_gate_hw(&clk_en_gpu),
> +		[RTD1625_CRT_CLK_EN_VE1]      = &__clk_regmap_gate_hw(&clk_en_ve1),
> +		[RTD1625_CRT_CLK_EN_VE2]      = &__clk_regmap_gate_hw(&clk_en_ve2),
> +		[RTD1625_CRT_CLK_EN_MD]       = &__clk_regmap_gate_hw(&clk_en_md),
> +		[RTD1625_CRT_CLK_EN_TP]       = &__clk_regmap_gate_hw(&clk_en_tp),
> +		[RTD1625_CRT_CLK_EN_RCIC]     = &__clk_regmap_gate_hw(&clk_en_rcic),
> +		[RTD1625_CRT_CLK_EN_NF]       = &__clk_regmap_gate_hw(&clk_en_nf),
> +		[RTD1625_CRT_CLK_EN_EMMC]     = &__clk_regmap_gate_hw(&clk_en_emmc),
> +		[RTD1625_CRT_CLK_EN_SD]       = &__clk_regmap_gate_hw(&clk_en_sd),
> +		[RTD1625_CRT_CLK_EN_SDIO_IP]  = &__clk_regmap_gate_hw(&clk_en_sdio_ip),
> +		[RTD1625_CRT_CLK_EN_MIPI_CSI] = &__clk_regmap_gate_hw(&clk_en_mipi_csi),
> +		[RTD1625_CRT_CLK_EN_EMMC_IP]  = &__clk_regmap_gate_hw(&clk_en_emmc_ip),
> +		[RTD1625_CRT_CLK_EN_SDIO]     = &__clk_regmap_gate_hw(&clk_en_sdio),
> +		[RTD1625_CRT_CLK_EN_SD_IP]    = &__clk_regmap_gate_hw(&clk_en_sd_ip),
> +		[RTD1625_CRT_CLK_EN_TPB]      = &__clk_regmap_gate_hw(&clk_en_tpb),
> +		[RTD1625_CRT_CLK_EN_MISC_SC1] = &__clk_regmap_gate_hw(&clk_en_misc_sc1),
> +		[RTD1625_CRT_CLK_EN_MISC_I2C_3] = &__clk_regmap_gate_hw(&clk_en_misc_i2c_3),
> +		[RTD1625_CRT_CLK_EN_ACPU]     = &__clk_regmap_gate_hw(&clk_en_acpu),
> +		[RTD1625_CRT_CLK_EN_JPEG]     = &__clk_regmap_gate_hw(&clk_en_jpeg),
> +		[RTD1625_CRT_CLK_EN_MISC_SC0] = &__clk_regmap_gate_hw(&clk_en_misc_sc0),
> +		[RTD1625_CRT_CLK_EN_HDMIRX]   = &__clk_regmap_gate_hw(&clk_en_hdmirx),
> +		[RTD1625_CRT_CLK_EN_HSE]      = &__clk_regmap_gate_hw(&clk_en_hse),
> +		[RTD1625_CRT_CLK_EN_FAN]      = &__clk_regmap_gate_hw(&clk_en_fan),
> +		[RTD1625_CRT_CLK_EN_SATA_WRAP_SYS] = &__clk_regmap_gate_hw(&clk_en_sata_wrap_sys),
> +		[RTD1625_CRT_CLK_EN_SATA_WRAP_SYSH] = &__clk_regmap_gate_hw(&clk_en_sata_wrap_sysh),
> +		[RTD1625_CRT_CLK_EN_SATA_MAC_SYSH] = &__clk_regmap_gate_hw(&clk_en_sata_mac_sysh),
> +		[RTD1625_CRT_CLK_EN_R2RDSC]   = &__clk_regmap_gate_hw(&clk_en_r2rdsc),
> +		[RTD1625_CRT_CLK_EN_PCIE1]    = &__clk_regmap_gate_hw(&clk_en_pcie1),
> +		[RTD1625_CRT_CLK_EN_MISC_I2C_4] = &__clk_regmap_gate_hw(&clk_en_misc_i2c_4),
> +		[RTD1625_CRT_CLK_EN_MISC_I2C_5] = &__clk_regmap_gate_hw(&clk_en_misc_i2c_5),
> +		[RTD1625_CRT_CLK_EN_TSIO]     = &__clk_regmap_gate_hw(&clk_en_tsio),
> +		[RTD1625_CRT_CLK_EN_VE4]      = &__clk_regmap_gate_hw(&clk_en_ve4),
> +		[RTD1625_CRT_CLK_EN_EDP]      = &__clk_regmap_gate_hw(&clk_en_edp),
> +		[RTD1625_CRT_CLK_EN_TSIO_TRX] = &__clk_regmap_gate_hw(&clk_en_tsio_trx),
> +		[RTD1625_CRT_CLK_EN_PCIE2]    = &__clk_regmap_gate_hw(&clk_en_pcie2),
> +		[RTD1625_CRT_CLK_EN_EARC]     = &__clk_regmap_gate_hw(&clk_en_earc),
> +		[RTD1625_CRT_CLK_EN_LITE]     = &__clk_regmap_gate_hw(&clk_en_lite),
> +		[RTD1625_CRT_CLK_EN_MIPI_DSI] = &__clk_regmap_gate_hw(&clk_en_mipi_dsi),
> +		[RTD1625_CRT_CLK_EN_NPUPP]    = &__clk_regmap_gate_hw(&clk_en_npupp),
> +		[RTD1625_CRT_CLK_EN_NPU]      = &__clk_regmap_gate_hw(&clk_en_npu),
> +		[RTD1625_CRT_CLK_EN_AUCPU0]   = &__clk_regmap_gate_hw(&clk_en_aucpu0),
> +		[RTD1625_CRT_CLK_EN_AUCPU1]   = &__clk_regmap_gate_hw(&clk_en_aucpu1),
> +		[RTD1625_CRT_CLK_EN_NSRAM]    = &__clk_regmap_gate_hw(&clk_en_nsram),
> +		[RTD1625_CRT_CLK_EN_HDMITOP]  = &__clk_regmap_gate_hw(&clk_en_hdmitop),
> +		[RTD1625_CRT_CLK_EN_AUCPU_ISO_NPU] = &__clk_regmap_gate_hw(&clk_en_aucpu_iso_npu),
> +		[RTD1625_CRT_CLK_EN_KEYLADDER] = &__clk_regmap_gate_hw(&clk_en_keyladder),
> +		[RTD1625_CRT_CLK_EN_IFCP_KLM]  = &__clk_regmap_gate_hw(&clk_en_ifcp_klm),
> +		[RTD1625_CRT_CLK_EN_IFCP]      = &__clk_regmap_gate_hw(&clk_en_ifcp),
> +		[RTD1625_CRT_CLK_EN_MDL_GENPW] = &__clk_regmap_gate_hw(&clk_en_mdl_genpw),
> +		[RTD1625_CRT_CLK_EN_MDL_CHIP]  = &__clk_regmap_gate_hw(&clk_en_mdl_chip),
> +		[RTD1625_CRT_CLK_EN_MDL_IP]    = &__clk_regmap_gate_hw(&clk_en_mdl_ip),
> +		[RTD1625_CRT_CLK_EN_MDLM2M]    = &__clk_regmap_gate_hw(&clk_en_mdlm2m),
> +		[RTD1625_CRT_CLK_EN_MDL_XTAL]  = &__clk_regmap_gate_hw(&clk_en_mdl_xtal),
> +		[RTD1625_CRT_CLK_EN_TEST_MUX]  = &__clk_regmap_gate_hw(&clk_en_test_mux),
> +		[RTD1625_CRT_CLK_EN_DLA]       = &__clk_regmap_gate_hw(&clk_en_dla),
> +		[RTD1625_CRT_CLK_EN_TPCW]      = &__clk_regmap_gate_hw(&clk_en_tpcw),
> +		[RTD1625_CRT_CLK_EN_GPU_TS_SRC] = &__clk_regmap_gate_hw(&clk_en_gpu_ts_src),
> +		[RTD1625_CRT_CLK_EN_VI]        = &__clk_regmap_gate_hw(&clk_en_vi),
> +		[RTD1625_CRT_CLK_EN_LVDS1]     = &__clk_regmap_gate_hw(&clk_en_lvds1),
> +		[RTD1625_CRT_CLK_EN_LVDS2]     = &__clk_regmap_gate_hw(&clk_en_lvds2),
> +		[RTD1625_CRT_CLK_EN_AUCPU]     = &__clk_regmap_gate_hw(&clk_en_aucpu),
> +		[RTD1625_CRT_CLK_EN_UR1]       = &__clk_regmap_gate_hw(&clk_en_ur1),
> +		[RTD1625_CRT_CLK_EN_UR2]       = &__clk_regmap_gate_hw(&clk_en_ur2),
> +		[RTD1625_CRT_CLK_EN_UR3]       = &__clk_regmap_gate_hw(&clk_en_ur3),
> +		[RTD1625_CRT_CLK_EN_UR4]       = &__clk_regmap_gate_hw(&clk_en_ur4),
> +		[RTD1625_CRT_CLK_EN_UR5]       = &__clk_regmap_gate_hw(&clk_en_ur5),
> +		[RTD1625_CRT_CLK_EN_UR6]       = &__clk_regmap_gate_hw(&clk_en_ur6),
> +		[RTD1625_CRT_CLK_EN_UR7]       = &__clk_regmap_gate_hw(&clk_en_ur7),
> +		[RTD1625_CRT_CLK_EN_UR8]       = &__clk_regmap_gate_hw(&clk_en_ur8),
> +		[RTD1625_CRT_CLK_EN_UR9]       = &__clk_regmap_gate_hw(&clk_en_ur9),
> +		[RTD1625_CRT_CLK_EN_UR_TOP]    = &__clk_regmap_gate_hw(&clk_en_ur_top),
> +		[RTD1625_CRT_CLK_EN_MISC_I2C_7] = &__clk_regmap_gate_hw(&clk_en_misc_i2c_7),
> +		[RTD1625_CRT_CLK_EN_MISC_I2C_6] = &__clk_regmap_gate_hw(&clk_en_misc_i2c_6),
> +		[RTD1625_CRT_CLK_EN_SPI0]      = &__clk_regmap_gate_hw(&clk_en_spi0),
> +		[RTD1625_CRT_CLK_EN_SPI1]      = &__clk_regmap_gate_hw(&clk_en_spi1),
> +		[RTD1625_CRT_CLK_EN_SPI2]      = &__clk_regmap_gate_hw(&clk_en_spi2),
> +		[RTD1625_CRT_CLK_EN_LSADC0]    = &__clk_regmap_gate_hw(&clk_en_lsadc0),
> +		[RTD1625_CRT_CLK_EN_LSADC1]    = &__clk_regmap_gate_hw(&clk_en_lsadc1),
> +		[RTD1625_CRT_CLK_EN_ISOMIS_DMA] = &__clk_regmap_gate_hw(&clk_en_isomis_dma),
> +		[RTD1625_CRT_CLK_EN_DPTX]      = &__clk_regmap_gate_hw(&clk_en_dptx),
> +		[RTD1625_CRT_CLK_EN_NPU_MIPI_CSI] = &__clk_regmap_gate_hw(&clk_en_npu_mipi_csi),
> +		[RTD1625_CRT_CLK_EN_EDPTX] = &__clk_regmap_gate_hw(&clk_en_edptx),
> +		[RTD1625_CRT_CLK_GPU]          = &__clk_regmap_mux_hw(&clk_gpu),
> +		[RTD1625_CRT_CLK_VE1]          = &__clk_regmap_mux_hw(&clk_ve1),
> +		[RTD1625_CRT_CLK_VE2]          = &__clk_regmap_mux_hw(&clk_ve2),
> +		[RTD1625_CRT_CLK_VE4]          = &__clk_regmap_mux_hw(&clk_ve4),
> +		[RTD1625_CRT_PLL_VE1]          = &__clk_pll_hw(&pll_ve1),
> +		[RTD1625_CRT_PLL_DDSA]         = &__clk_pll_hw(&pll_ddsa),
> +		[RTD1625_CRT_PLL_BUS]          = &__clk_pll_hw(&pll_bus),
> +		[RTD1625_CRT_CLK_SYS]          = &clk_sys.hw,
> +		[RTD1625_CRT_PLL_DCSB]         = &__clk_pll_hw(&pll_dcsb),
> +		[RTD1625_CRT_CLK_SYSH]         = &clk_sysh.hw,
> +		[RTD1625_CRT_PLL_GPU]          = &__clk_pll_hw(&pll_gpu),
> +		[RTD1625_CRT_PLL_NPU]          = &__clk_pll_hw(&pll_npu),
> +		[RTD1625_CRT_PLL_VE2]          = &__clk_pll_hw(&pll_ve2),
> +		[RTD1625_CRT_PLL_HIFI]         = &__clk_pll_hw(&pll_hifi),
> +		[RTD1625_CRT_PLL_EMMC_REF]     = &pll_emmc_ref.hw,
> +		[RTD1625_CRT_PLL_EMMC]         = &__clk_pll_mmc_hw(&pll_emmc),
> +		[RTD1625_CRT_PLL_EMMC_VP0]     = &pll_emmc.phase0_hw,
> +		[RTD1625_CRT_PLL_EMMC_VP1]     = &pll_emmc.phase1_hw,
> +		[RTD1625_CRT_PLL_ACPU]         = &__clk_pll_hw(&pll_acpu),
> +		[RTD1625_CRT_CLK_NPU]          = &clk_npu.hw,
> +		[RTD1625_CRT_CLK_NPU_MIPI_CSI] = &clk_npu_mipi_csi.hw,
> +
> +		[RTD1625_CRT_CLK_MAX]          = NULL,
> +	},
> +};
> +
> +static const struct rtk_clk_desc rtd1625_crt_desc = {
> +	.clk_data        = &rtd1625_crt_hw_data,
> +	.clks            = rtd1625_crt_regmap_clks,
> +	.num_clks        = ARRAY_SIZE(rtd1625_crt_regmap_clks),
> +};
> +
> +static int rtd1625_crt_probe(struct platform_device *pdev)
> +{
> +	const struct rtk_clk_desc *desc;
> +
> +	desc = of_device_get_match_data(&pdev->dev);
> +	if (!desc)
> +		return -EINVAL;
> +
> +	return rtk_clk_probe(pdev, desc, "crt_rst");
> +}
> +
> +static const struct of_device_id rtd1625_crt_match[] = {
> +	{.compatible = "realtek,rtd1625-crt-clk", .data = &rtd1625_crt_desc,},
> +	{/* sentinel */}

Add a space around the comment like so:

{ /* sentinel */ }

> +};
> +
> +static struct platform_driver rtd1625_crt_driver = {
> +	.probe = rtd1625_crt_probe,
> +	.driver = {
> +		.name = "rtk-rtd1625-crt-clk",
> +		.of_match_table = rtd1625_crt_match,
> +	},
> +};
> +
> +static int __init rtd1625_crt_init(void)
> +{
> +	return platform_driver_register(&rtd1625_crt_driver);
> +}
> +subsys_initcall(rtd1625_crt_init);
> +
> +MODULE_DESCRIPTION("Reatek RTD1625 CRT Controller Driver");

s/Reatek/Realtex/

> +MODULE_AUTHOR("Cheng-Yu Lee <cylee12@realtek.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("REALTEK_CLK");
> diff --git a/drivers/reset/realtek/Kconfig b/drivers/reset/realtek/Kconfig
> index 99a14d355803..a44c7834191c 100644
> --- a/drivers/reset/realtek/Kconfig
> +++ b/drivers/reset/realtek/Kconfig
> @@ -1,3 +1,5 @@
>  # SPDX-License-Identifier: GPL-2.0-only
>  config RESET_RTK_COMMON
>  	bool
> +	select AUXILIARY_BUS
> +	default COMMON_CLK_RTD1625
> diff --git a/drivers/reset/realtek/Makefile b/drivers/reset/realtek/Makefile
> index b59a3f7f2453..8ca1fa939f10 100644
> --- a/drivers/reset/realtek/Makefile
> +++ b/drivers/reset/realtek/Makefile
> @@ -1,2 +1,2 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> -obj-$(CONFIG_RESET_RTK_COMMON) += common.o
> +obj-$(CONFIG_RESET_RTK_COMMON) += common.o reset-rtd1625-crt.o

CONFIG_RESET_RTK_COMMON is supposed to be common, right? If so, the
SoC-specific driver shouldn't be included here.

> diff --git a/drivers/reset/realtek/reset-rtd1625-crt.c b/drivers/reset/realtek/reset-rtd1625-crt.c
> new file mode 100644
> index 000000000000..ebb15bb68885
> --- /dev/null
> +++ b/drivers/reset/realtek/reset-rtd1625-crt.c
> @@ -0,0 +1,186 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Realtek Semiconductor Corporation
> + */
> +
> +#include <dt-bindings/reset/realtek,rtd1625.h>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/slab.h>
> +#include "common.h"
> +
> +#define RTD1625_CRT_RSTN_MAX	123
> +
> +static struct rtk_reset_desc rtd1625_crt_reset_descs[] = {
> +	/* Bank 0: offset 0x0 */
> +	[RTD1625_CRT_RSTN_MISC]         = { .ofs = 0x0, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DIP]          = { .ofs = 0x0, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GSPI]         = { .ofs = 0x0, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS]          = { .ofs = 0x0, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS_REG]      = { .ofs = 0x0, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDS_PHY]      = { .ofs = 0x0, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GPU2D]        = { .ofs = 0x0, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DC_PHY]       = { .ofs = 0x0, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_CRT]    = { .ofs = 0x0, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC]        = { .ofs = 0x0, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SE]           = { .ofs = 0x0, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DLA]          = { .ofs = 0x0, .bit = 30, .write_en = 1 },

Sashiko reports:
https://sashiko.dev/#/patchset/20260402073957.2742459-1-eleanor.lin%40realtek.com

    Can this cause undefined behavior during reset mask computation?
    
    Several reset array entries set .bit = 30 and .write_en = 1. In
    rtk_reset_assert() and rtk_reset_deassert(), if the bitmask is computed as
    0x3 << desc->bit, 0x3 is a signed 32-bit integer literal. Left-shifting it by
    30 results in 0xC0000000, which exceeds the maximum positive value for a
    signed 32-bit integer.
    
    Modifying the sign bit via left-shift on a signed type invokes undefined
    behavior in C. Would an unsigned literal (e.g., 0x3U << desc->bit) be needed
    to safely construct the mask?

> +	/* Bank 1: offset 0x4 */
> +	[RTD1625_CRT_RSTN_JPEG]         = { .ofs = 0x4, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SD]           = { .ofs = 0x4, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SDIO]         = { .ofs = 0x4, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCR_CNT]      = { .ofs = 0x4, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_STITCH] = { .ofs = 0x4, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_PHY]    = { .ofs = 0x4, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0]        = { .ofs = 0x4, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_CORE]   = { .ofs = 0x4, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_POWER]  = { .ofs = 0x4, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_NONSTICH] = { .ofs = 0x4, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_PHY_MDIO] = { .ofs = 0x4, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE0_SGMII_MDIO] = { .ofs = 0x4, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VO2]          = { .ofs = 0x4, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MISC_SC0]     = { .ofs = 0x4, .bit = 30, .write_en = 1 },
> +	/* Bank 2: offset 0x8 */
> +	[RTD1625_CRT_RSTN_MD]           = { .ofs = 0x8, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LVDS1]        = { .ofs = 0x8, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LVDS2]        = { .ofs = 0x8, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MISC_SC1]     = { .ofs = 0x8, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_3]        = { .ofs = 0x8, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_FAN]          = { .ofs = 0x8, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TVE]          = { .ofs = 0x8, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AIO]          = { .ofs = 0x8, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VO]           = { .ofs = 0x8, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MIPI_CSI]     = { .ofs = 0x8, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMIRX]       = { .ofs = 0x8, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMIRX_WRAP]  = { .ofs = 0x8, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMI]         = { .ofs = 0x8, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DISP]         = { .ofs = 0x8, .bit = 30, .write_en = 1 },
> +	/* Bank 3: offset 0xc */
> +	[RTD1625_CRT_RSTN_SATA_PHY_POW1] = { .ofs = 0xc, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_PHY_POW0] = { .ofs = 0xc, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MDIO1]   = { .ofs = 0xc, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MDIO0]   = { .ofs = 0xc, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_WRAP]    = { .ofs = 0xc, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_P1]  = { .ofs = 0xc, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_P0]  = { .ofs = 0xc, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SATA_MAC_COM] = { .ofs = 0xc, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_STITCH] = { .ofs = 0xc, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_PHY]     = { .ofs = 0xc, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1]         = { .ofs = 0xc, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_CORE]   = { .ofs = 0xc, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_POWER]  = { .ofs = 0xc, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_NONSTICH] = { .ofs = 0xc, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE1_PHY_MDIO] = { .ofs = 0xc, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HDMITOP]      = { .ofs = 0xc, .bit = 30, .write_en = 1 },
> +	/* Bank 4: offset 0x68 */
> +	[RTD1625_CRT_RSTN_I2C_4]        = { .ofs = 0x68, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_5]        = { .ofs = 0x68, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TSIO]         = { .ofs = 0x68, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VI]           = { .ofs = 0x68, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EDP]          = { .ofs = 0x68, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_MMU]      = { .ofs = 0x68, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_MMU_FUNC] = { .ofs = 0x68, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HSE_MMU]      = { .ofs = 0x68, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HSE_MMU_FUNC] = { .ofs = 0x68, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDLM2M]       = { .ofs = 0x68, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_ISO_GSPI]     = { .ofs = 0x68, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SOFT_NPU]     = { .ofs = 0x68, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI2EMMC]     = { .ofs = 0x68, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EARC]         = { .ofs = 0x68, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1]          = { .ofs = 0x68, .bit = 30, .write_en = 1 },
> +	/* Bank 5: offset 0x90 */
> +	[RTD1625_CRT_RSTN_PCIE2_STITCH]  = { .ofs = 0x90, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_PHY]    = { .ofs = 0x90, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2]        = { .ofs = 0x90, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_CORE]   = { .ofs = 0x90, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_POWER]  = { .ofs = 0x90, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_NONSTICH] = { .ofs = 0x90, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_PCIE2_PHY_MDIO] = { .ofs = 0x90, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_UMCTL2] = { .ofs = 0x90, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MIPI_DSI]     = { .ofs = 0x90, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_HIFM]         = { .ofs = 0x90, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_NSRAM]        = { .ofs = 0x90, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUCPU0_REG]   = { .ofs = 0x90, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_GENPW]    = { .ofs = 0x90, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_CHIP]     = { .ofs = 0x90, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MDL_IP]       = { .ofs = 0x90, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_TEST_MUX]     = { .ofs = 0x90, .bit = 30, .write_en = 1 },
> +	/* Bank 6: offset 0xb8 */
> +	[RTD1625_CRT_RSTN_ISO_BIST]     = { .ofs = 0xb8, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MAIN_BIST]    = { .ofs = 0xb8, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_MAIN2_BIST]   = { .ofs = 0xb8, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE1_BIST]     = { .ofs = 0xb8, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE2_BIST]     = { .ofs = 0xb8, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DCPHY_BIST]   = { .ofs = 0xb8, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_GPU_BIST]     = { .ofs = 0xb8, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DISP_BIST]    = { .ofs = 0xb8, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_NPU_BIST]     = { .ofs = 0xb8, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_CAS_BIST]     = { .ofs = 0xb8, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_VE4_BIST]     = { .ofs = 0xb8, .bit = 20, .write_en = 1 },
> +	/* Bank 7: offset 0x454 (DUMMY0, no write_en) */
> +	[RTD1625_CRT_RSTN_EMMC]         = { .ofs = 0x454, .bit = 0 },
> +	/* Bank 8: offset 0x458 (DUMMY1, no write_en) */
> +	[RTD1625_CRT_RSTN_GPU]          = { .ofs = 0x458, .bit = 0 },
> +	/* Bank 9: offset 0x464 (DUMMY4, no write_en) */
> +	[RTD1625_CRT_RSTN_VE2]          = { .ofs = 0x464, .bit = 0 },
> +	/* Bank 10: offset 0x880 */
> +	[RTD1625_CRT_RSTN_UR1]          = { .ofs = 0x880, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR2]          = { .ofs = 0x880, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR3]          = { .ofs = 0x880, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR4]          = { .ofs = 0x880, .bit = 6,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR5]          = { .ofs = 0x880, .bit = 8,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR6]          = { .ofs = 0x880, .bit = 10, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR7]          = { .ofs = 0x880, .bit = 12, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR8]          = { .ofs = 0x880, .bit = 14, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR9]          = { .ofs = 0x880, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_UR_TOP]       = { .ofs = 0x880, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_7]        = { .ofs = 0x880, .bit = 28, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_I2C_6]        = { .ofs = 0x880, .bit = 30, .write_en = 1 },
> +	/* Bank 11: offset 0x890 */
> +	[RTD1625_CRT_RSTN_SPI0]         = { .ofs = 0x890, .bit = 0,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI1]         = { .ofs = 0x890, .bit = 2,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_SPI2]         = { .ofs = 0x890, .bit = 4,  .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC0]       = { .ofs = 0x890, .bit = 16, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_LSADC1]       = { .ofs = 0x890, .bit = 18, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_ISOMIS_DMA]   = { .ofs = 0x890, .bit = 20, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUDIO_ADC]    = { .ofs = 0x890, .bit = 22, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_DPTX]         = { .ofs = 0x890, .bit = 24, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_AUCPU1_REG]   = { .ofs = 0x890, .bit = 26, .write_en = 1 },
> +	[RTD1625_CRT_RSTN_EDPTX]        = { .ofs = 0x890, .bit = 28, .write_en = 1 },
> +};
> +
> +static int rtd1625_crt_reset_probe(struct auxiliary_device *adev,
> +				   const struct auxiliary_device_id *id)
> +{
> +	struct device *dev = &adev->dev;
> +	struct rtk_reset_data *data;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->descs           = rtd1625_crt_reset_descs;
> +	data->rcdev.nr_resets = RTD1625_CRT_RSTN_MAX;
> +	return rtk_reset_controller_add(dev, data);

Sashiko reports:
https://sashiko.dev/#/patchset/20260402073957.2742459-1-eleanor.lin%40realtek.com

    Will the reset controller driver unconditionally fail to probe with -ENODEV
    due to an incompatible regmap acquisition method?
    
    The rtk_reset_controller_add() helper attempts to retrieve the shared regmap
    from the parent clock device using dev_get_regmap(parent, NULL). However, the
    parent clock driver (rtk_clk_probe()) acquires its regmap via
    device_node_to_regmap().
    
    This syscon helper creates the regmap but does not associate it with the
    parent struct device via devres. Because the regmap is absent from the
    parent's devres list, dev_get_regmap() will always return NULL, causing the
    reset driver probe to fail unconditionally and leaving dependent peripherals
    without reset control.

Brian


> +}
> +
> +static const struct auxiliary_device_id rtd1625_crt_reset_ids[] = {
> +	{
> +		.name = "clk_rtk.crt_rst",
> +	},
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(auxiliary, rtd1625_crt_reset_ids);
> +
> +static struct auxiliary_driver rtd1625_crt_driver = {
> +	.probe    = rtd1625_crt_reset_probe,
> +	.id_table = rtd1625_crt_reset_ids,
> +	.driver = {
> +		.name = "rtd1625-crt-reset",
> +	},
> +};
> +module_auxiliary_driver(rtd1625_crt_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("REALTEK_RESET");
> -- 
> 2.34.1
> 



^ permalink raw reply

* Re: [PATCH v6 09/10] clk: realtek: Add RTD1625-ISO clock controller driver
From: Brian Masney @ 2026-04-03 15:29 UTC (permalink / raw)
  To: Yu-Chun Lin
  Cc: mturquette, sboyd, robh, krzk+dt, conor+dt, p.zabel, cylee12,
	afaerber, jyanchou, devicetree, linux-clk, linux-kernel,
	linux-arm-kernel, linux-realtek-soc, james.tai, cy.huang,
	stanley_chang
In-Reply-To: <20260402073957.2742459-10-eleanor.lin@realtek.com>

Hi Yu-Chun,

On Thu, Apr 02, 2026 at 03:39:56PM +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Add support for the ISO (Isolation) domain clock controller on the Realtek
> RTD1625 SoC. This controller manages clocks in the always-on power domain,
> ensuring essential services remain functional even when the main system
> power is gated.
> 
> Since the reset controller shares the same register space with the ISO
> clock controller, it is instantiated as an auxiliary device by the core
> clock driver. This patch also includes the corresponding auxiliary reset
> driver to handle the ISO domain resets.
> 
> Signed-off-by: Cheng-Yu Lee <cylee12@realtek.com>
> Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
> ---
> Changes in v6:
> - Add the headers used in c file to follow the "Include What You Use" principle.
> - Move struct rtk_reset_desc arrays from the clock driver to the dedicated reset driver.
> - Implement and register a dedicated reset auxiliary driver.
> ---
>  drivers/clk/realtek/Makefile              |   1 +
>  drivers/clk/realtek/clk-rtd1625-iso.c     | 144 ++++++++++++++++++++++
>  drivers/reset/realtek/Makefile            |   2 +-
>  drivers/reset/realtek/reset-rtd1625-iso.c |  96 +++++++++++++++
>  4 files changed, 242 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/clk/realtek/clk-rtd1625-iso.c
>  create mode 100644 drivers/reset/realtek/reset-rtd1625-iso.c
> 
> diff --git a/drivers/clk/realtek/Makefile b/drivers/clk/realtek/Makefile
> index c992f97dfbc7..1680435e1e0f 100644
> --- a/drivers/clk/realtek/Makefile
> +++ b/drivers/clk/realtek/Makefile
> @@ -10,3 +10,4 @@ clk-rtk-y += freq_table.o
>  
>  clk-rtk-$(CONFIG_RTK_CLK_PLL_MMC) += clk-pll-mmc.o
>  obj-$(CONFIG_COMMON_CLK_RTD1625) += clk-rtd1625-crt.o
> +obj-$(CONFIG_COMMON_CLK_RTD1625) += clk-rtd1625-iso.o
> diff --git a/drivers/clk/realtek/clk-rtd1625-iso.c b/drivers/clk/realtek/clk-rtd1625-iso.c
> new file mode 100644
> index 000000000000..027a131363f9
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtd1625-iso.c
> @@ -0,0 +1,144 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2024 Realtek Semiconductor Corporation
> + * Author: Cheng-Yu Lee <cylee12@realtek.com>
> + */
> +
> +#include <dt-bindings/clock/realtek,rtd1625-clk.h>
> +#include <linux/array_size.h>
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include "clk-regmap-gate.h"
> +
> +#define RTD1625_ISO_CLK_MAX	19
> +#define RTD1625_ISO_RSTN_MAX	29
> +#define RTD1625_ISO_S_CLK_MAX	5
> +#define RTD1625_ISO_S_RSTN_MAX	5
> +
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb_p4, 0, 0x4, 0, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb_p3, 0, 0x4, 1, 0);
> +static CLK_REGMAP_GATE(clk_en_misc_cec0, "clk_en_misc", 0, 0x4, 2, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_cbusrx_sys, 0, 0x4, 3, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_cbustx_sys, 0, 0x4, 4, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_cbus_sys, 0, 0x4, 5, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_cbus_osc, 0, 0x4, 6, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_i2c0, 0, 0x4, 9, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_i2c1, 0, 0x4, 10, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_etn_250m, 0, 0x4, 11, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_etn_sys, 0, 0x4, 12, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb_drd, 0, 0x4, 13, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb_host, 0, 0x4, 14, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb_u3_host, 0, 0x4, 15, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_usb, 0, 0x4, 16, 0);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_vtc, 0, 0x4, 17, 0);
> +static CLK_REGMAP_GATE(clk_en_misc_vfd, "clk_en_misc", 0, 0x4, 18, 0);
> +
> +static struct clk_regmap *rtd1625_clk_regmap_list[] = {

static const? Same for some others below as well.

> +	&clk_en_usb_p4.clkr,
> +	&clk_en_usb_p3.clkr,
> +	&clk_en_misc_cec0.clkr,
> +	&clk_en_cbusrx_sys.clkr,
> +	&clk_en_cbustx_sys.clkr,
> +	&clk_en_cbus_sys.clkr,
> +	&clk_en_cbus_osc.clkr,
> +	&clk_en_i2c0.clkr,
> +	&clk_en_i2c1.clkr,
> +	&clk_en_etn_250m.clkr,
> +	&clk_en_etn_sys.clkr,
> +	&clk_en_usb_drd.clkr,
> +	&clk_en_usb_host.clkr,
> +	&clk_en_usb_u3_host.clkr,
> +	&clk_en_usb.clkr,
> +	&clk_en_vtc.clkr,
> +	&clk_en_misc_vfd.clkr,
> +};
> +
> +static struct clk_hw_onecell_data rtd1625_iso_clk_data = {
> +	.num = RTD1625_ISO_CLK_MAX,
> +	.hws = {
> +		[RTD1625_ISO_CLK_EN_USB_P4]      = &__clk_regmap_gate_hw(&clk_en_usb_p4),
> +		[RTD1625_ISO_CLK_EN_USB_P3]      = &__clk_regmap_gate_hw(&clk_en_usb_p3),
> +		[RTD1625_ISO_CLK_EN_MISC_CEC0]   = &__clk_regmap_gate_hw(&clk_en_misc_cec0),
> +		[RTD1625_ISO_CLK_EN_CBUSRX_SYS]  = &__clk_regmap_gate_hw(&clk_en_cbusrx_sys),
> +		[RTD1625_ISO_CLK_EN_CBUSTX_SYS]  = &__clk_regmap_gate_hw(&clk_en_cbustx_sys),
> +		[RTD1625_ISO_CLK_EN_CBUS_SYS]    = &__clk_regmap_gate_hw(&clk_en_cbus_sys),
> +		[RTD1625_ISO_CLK_EN_CBUS_OSC]    = &__clk_regmap_gate_hw(&clk_en_cbus_osc),
> +		[RTD1625_ISO_CLK_EN_I2C0]        = &__clk_regmap_gate_hw(&clk_en_i2c0),
> +		[RTD1625_ISO_CLK_EN_I2C1]        = &__clk_regmap_gate_hw(&clk_en_i2c1),
> +		[RTD1625_ISO_CLK_EN_ETN_250M]    = &__clk_regmap_gate_hw(&clk_en_etn_250m),
> +		[RTD1625_ISO_CLK_EN_ETN_SYS]     = &__clk_regmap_gate_hw(&clk_en_etn_sys),
> +		[RTD1625_ISO_CLK_EN_USB_DRD]     = &__clk_regmap_gate_hw(&clk_en_usb_drd),
> +		[RTD1625_ISO_CLK_EN_USB_HOST]    = &__clk_regmap_gate_hw(&clk_en_usb_host),
> +		[RTD1625_ISO_CLK_EN_USB_U3_HOST] = &__clk_regmap_gate_hw(&clk_en_usb_u3_host),
> +		[RTD1625_ISO_CLK_EN_USB]         = &__clk_regmap_gate_hw(&clk_en_usb),
> +		[RTD1625_ISO_CLK_EN_VTC]         = &__clk_regmap_gate_hw(&clk_en_vtc),
> +		[RTD1625_ISO_CLK_EN_MISC_VFD]    = &__clk_regmap_gate_hw(&clk_en_misc_vfd),
> +		[RTD1625_ISO_CLK_MAX] = NULL,
> +	},
> +};
> +
> +static const struct rtk_clk_desc rtd1625_iso_desc = {
> +	.clk_data = &rtd1625_iso_clk_data,
> +	.clks     = rtd1625_clk_regmap_list,
> +	.num_clks = ARRAY_SIZE(rtd1625_clk_regmap_list),
> +};
> +
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_irda, 0, 0x4, 6, 1);
> +static CLK_REGMAP_GATE_NO_PARENT(clk_en_ur10, 0, 0x4, 8, 1);
> +
> +static struct clk_regmap *rtd1625_iso_s_clk_regmap_list[] = {
> +	&clk_en_irda.clkr,
> +	&clk_en_ur10.clkr,
> +};
> +
> +static struct clk_hw_onecell_data rtd1625_iso_s_clk_data = {
> +	.num = RTD1625_ISO_S_CLK_MAX,
> +	.hws = {
> +		[RTD1625_ISO_S_CLK_EN_IRDA] = &__clk_regmap_gate_hw(&clk_en_irda),
> +		[RTD1625_ISO_S_CLK_EN_UR10] = &__clk_regmap_gate_hw(&clk_en_ur10),
> +		[RTD1625_ISO_S_CLK_MAX] = NULL,
> +	},
> +};
> +
> +static const struct rtk_clk_desc rtd1625_iso_s_desc = {
> +	.clk_data = &rtd1625_iso_s_clk_data,
> +	.clks     = rtd1625_iso_s_clk_regmap_list,
> +	.num_clks = ARRAY_SIZE(rtd1625_iso_s_clk_regmap_list),
> +};
> +
> +static int rtd1625_iso_probe(struct platform_device *pdev)
> +{
> +	const struct rtk_clk_desc *desc;
> +
> +	desc = of_device_get_match_data(&pdev->dev);
> +	if (!desc)
> +		return -EINVAL;
> +	return rtk_clk_probe(pdev, desc, "iso_rst");

Add newline before return.

> +}
> +
> +static const struct of_device_id rtd1625_iso_match[] = {
> +	{.compatible = "realtek,rtd1625-iso-clk", .data = &rtd1625_iso_desc},
> +	{.compatible = "realtek,rtd1625-iso-s-clk", .data = &rtd1625_iso_s_desc},
> +	{ /* sentinel */ }
> +};
> +
> +static struct platform_driver rtd1625_iso_driver = {
> +	.probe = rtd1625_iso_probe,
> +	.driver = {
> +		.name = "rtk-rtd1625-iso-clk",
> +		.of_match_table = rtd1625_iso_match,
> +	},
> +};
> +
> +static int __init rtd1625_iso_init(void)
> +{
> +	return platform_driver_register(&rtd1625_iso_driver);
> +}
> +subsys_initcall(rtd1625_iso_init);
> +
> +MODULE_DESCRIPTION("Realtek RTD1625 ISO Controller Driver");
> +MODULE_AUTHOR("Cheng-Yu Lee <cylee12@realtek.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("REALTEK_CLK");
> diff --git a/drivers/reset/realtek/Makefile b/drivers/reset/realtek/Makefile
> index 8ca1fa939f10..26b3ddc75ada 100644
> --- a/drivers/reset/realtek/Makefile
> +++ b/drivers/reset/realtek/Makefile
> @@ -1,2 +1,2 @@
>  # SPDX-License-Identifier: GPL-2.0-only
> -obj-$(CONFIG_RESET_RTK_COMMON) += common.o reset-rtd1625-crt.o
> +obj-$(CONFIG_RESET_RTK_COMMON) += common.o reset-rtd1625-crt.o reset-rtd1625-iso.o

Some comment as the previous patch. CONFIG_RESET_RTK_COMMON is expected
to be common, right? If so, a SoC-specific driver shouldn't be listed
here.

> diff --git a/drivers/reset/realtek/reset-rtd1625-iso.c b/drivers/reset/realtek/reset-rtd1625-iso.c
> new file mode 100644
> index 000000000000..f2a0478382ae
> --- /dev/null
> +++ b/drivers/reset/realtek/reset-rtd1625-iso.c
> @@ -0,0 +1,96 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2026 Realtek Semiconductor Corporation
> + */
> +
> +#include <dt-bindings/reset/realtek,rtd1625.h>
> +#include <linux/auxiliary_bus.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +#include "common.h"
> +
> +#define RTD1625_ISO_RSTN_MAX	29
> +#define RTD1625_ISO_S_RSTN_MAX	5
> +
> +static struct rtk_reset_desc rtd1625_iso_reset_descs[] = {

static const?

> +	[RTD1625_ISO_RSTN_VFD]                 = { .ofs = 0x88, .bit = 0 },
> +	[RTD1625_ISO_RSTN_CEC0]                = { .ofs = 0x88, .bit = 2 },
> +	[RTD1625_ISO_RSTN_CEC1]                = { .ofs = 0x88, .bit = 3 },
> +	[RTD1625_ISO_RSTN_CBUSTX]              = { .ofs = 0x88, .bit = 5 },
> +	[RTD1625_ISO_RSTN_CBUSRX]              = { .ofs = 0x88, .bit = 6 },
> +	[RTD1625_ISO_RSTN_USB3_PHY2_XTAL_POW]  = { .ofs = 0x88, .bit = 7 },
> +	[RTD1625_ISO_RSTN_UR0]                 = { .ofs = 0x88, .bit = 8 },
> +	[RTD1625_ISO_RSTN_GMAC]                = { .ofs = 0x88, .bit = 9 },
> +	[RTD1625_ISO_RSTN_GPHY]                = { .ofs = 0x88, .bit = 10 },
> +	[RTD1625_ISO_RSTN_I2C_0]               = { .ofs = 0x88, .bit = 11 },
> +	[RTD1625_ISO_RSTN_I2C_1]               = { .ofs = 0x88, .bit = 12 },
> +	[RTD1625_ISO_RSTN_CBUS]                = { .ofs = 0x88, .bit = 13 },
> +	[RTD1625_ISO_RSTN_USB_DRD]             = { .ofs = 0x88, .bit = 14 },
> +	[RTD1625_ISO_RSTN_USB_HOST]            = { .ofs = 0x88, .bit = 15 },
> +	[RTD1625_ISO_RSTN_USB_PHY_0]           = { .ofs = 0x88, .bit = 16 },
> +	[RTD1625_ISO_RSTN_USB_PHY_1]           = { .ofs = 0x88, .bit = 17 },
> +	[RTD1625_ISO_RSTN_USB_PHY_2]           = { .ofs = 0x88, .bit = 18 },
> +	[RTD1625_ISO_RSTN_USB]                 = { .ofs = 0x88, .bit = 19 },
> +	[RTD1625_ISO_RSTN_TYPE_C]              = { .ofs = 0x88, .bit = 20 },
> +	[RTD1625_ISO_RSTN_USB_U3_HOST]         = { .ofs = 0x88, .bit = 21 },
> +	[RTD1625_ISO_RSTN_USB3_PHY0_POW]       = { .ofs = 0x88, .bit = 22 },
> +	[RTD1625_ISO_RSTN_USB3_P0_MDIO]        = { .ofs = 0x88, .bit = 23 },
> +	[RTD1625_ISO_RSTN_USB3_PHY1_POW]       = { .ofs = 0x88, .bit = 24 },
> +	[RTD1625_ISO_RSTN_USB3_P1_MDIO]        = { .ofs = 0x88, .bit = 25 },
> +	[RTD1625_ISO_RSTN_VTC]                 = { .ofs = 0x88, .bit = 26 },
> +	[RTD1625_ISO_RSTN_USB3_PHY2_POW]       = { .ofs = 0x88, .bit = 27 },
> +	[RTD1625_ISO_RSTN_USB3_P2_MDIO]        = { .ofs = 0x88, .bit = 28 },
> +	[RTD1625_ISO_RSTN_USB_PHY_3]           = { .ofs = 0x88, .bit = 29 },
> +	[RTD1625_ISO_RSTN_USB_PHY_4]           = { .ofs = 0x88, .bit = 30 },
> +};
> +
> +static struct rtk_reset_desc rtd1625_iso_s_reset_descs[] = {
> +	[RTD1625_ISO_S_RSTN_ISOM_MIS] = { .ofs = 0x310, .bit = 0, .write_en = 1 },
> +	[RTD1625_ISO_S_RSTN_GPIOM]    = { .ofs = 0x310, .bit = 2, .write_en = 1 },
> +	[RTD1625_ISO_S_RSTN_TIMER7]   = { .ofs = 0x310, .bit = 4, .write_en = 1 },
> +	[RTD1625_ISO_S_RSTN_IRDA]     = { .ofs = 0x310, .bit = 6, .write_en = 1 },
> +	[RTD1625_ISO_S_RSTN_UR10]     = { .ofs = 0x310, .bit = 8, .write_en = 1 },
> +};
> +
> +static int rtd1625_iso_reset_probe(struct auxiliary_device *adev,
> +				   const struct auxiliary_device_id *id)
> +{
> +	struct device *dev = &adev->dev;
> +	struct device *parent = dev->parent;
> +	struct rtk_reset_data *data;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	if (of_device_is_compatible(parent->of_node, "realtek,rtd1625-iso-s-clk")) {
> +		data->descs           = rtd1625_iso_s_reset_descs;
> +		data->rcdev.nr_resets = RTD1625_ISO_S_RSTN_MAX;
> +	} else {
> +		data->descs           = rtd1625_iso_reset_descs;
> +		data->rcdev.nr_resets = RTD1625_ISO_RSTN_MAX;
> +	}
> +	return rtk_reset_controller_add(dev, data);

Newline before return.

> +}
> +
> +static const struct auxiliary_device_id rtd1625_iso_reset_ids[] = {
> +	{
> +		.name = "clk_rtk.iso_rst",
> +	},

I would combine the { .name } all on one line.

Brian


> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(auxiliary, rtd1625_iso_reset_ids);
> +
> +static struct auxiliary_driver rtd1625_iso_driver = {
> +	.probe = rtd1625_iso_reset_probe,
> +	.id_table = rtd1625_iso_reset_ids,
> +	.driver = {
> +		.name = "rtd1625-iso-reset",
> +	},
> +};
> +module_auxiliary_driver(rtd1625_iso_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_IMPORT_NS("REALTEK_RESET");
> -- 
> 2.34.1
> 



^ permalink raw reply

* Re: [PATCH v20 06/10] power: reset: Add psci-reboot-mode driver
From: Lorenzo Pieralisi @ 2026-04-03 15:50 UTC (permalink / raw)
  To: Shivendra Pratap
  Cc: Arnd Bergmann, Bjorn Andersson, Sebastian Reichel, Rob Herring,
	Souvik Chakravarty, Krzysztof Kozlowski, Andy Yan,
	Matthias Brugger, Mark Rutland, Conor Dooley, Konrad Dybcio,
	John Stultz, Moritz Fischer, Bartosz Golaszewski, Sudeep Holla,
	Florian Fainelli, Krzysztof Kozlowski, Dmitry Baryshkov,
	Mukesh Ojha, Andre Draszik, Kathiravan Thirumoorthy, linux-pm,
	linux-kernel, linux-arm-kernel, linux-arm-msm, devicetree,
	Srinivas Kandagatla
In-Reply-To: <da6f4566-a719-409b-80a9-40ca89e3e721@oss.qualcomm.com>

On Fri, Apr 03, 2026 at 12:05:27AM +0530, Shivendra Pratap wrote:
> 
> 
> On 01-04-2026 20:07, Lorenzo Pieralisi wrote:
> > On Tue, Mar 31, 2026 at 11:30:09PM +0530, Shivendra Pratap wrote:
> > > 
> > > 
> > > On 27-03-2026 19:25, Lorenzo Pieralisi wrote:
> > > > On Wed, Mar 04, 2026 at 11:33:06PM +0530, Shivendra Pratap wrote:
> > > > > PSCI supports different types of resets like COLD reset, ARCH WARM
> 
> [snip..]
> 
> > > > > + * Predefined reboot-modes are defined as per the values
> > > > > + * of enum reboot_mode defined in the kernel: reboot.c.
> > > > > + */
> > > > > +static struct mode_info psci_resets[] = {
> > > > > +	{ .mode = "warm", .magic = REBOOT_WARM},
> > > > > +	{ .mode = "soft", .magic = REBOOT_SOFT},
> > > > > +	{ .mode = "cold", .magic = REBOOT_COLD},
> > 
> > These strings match the command userspace issue right ? I think that we
> > should make them match the corresponding PSCI reset types, the list above
> > maps command to reboot_mode values and those can belong to any reboot
> > mode driver to be honest they don't make much sense in a PSCI reboot
> > mode driver only.
> > 
> > It is a question for everyone here: would it make sense to make these
> > predefined resets a set of strings, eg:
> > 
> > psci-system-reset
> > psci-system-reset2-arch-warm-reset
> > 
> > and then vendor resets:
> > 
> > psci-system-reset2-vendor-reset
> 
> Can you share bit more details on this? We are already defining the string
> from userspace in the struct - eg: ".mode = "warm".

"warm","soft","cold" are not strictly speaking PSCI concepts and mean nothing
well defined to user space and even if they did, they would not belong in
the PSCI reboot mode driver but in generic code.

Spelling out what a reset is might help instead, again, this is just my
opinion, I don't know how the semantics of resets have been handled thus
far.

If userspace issues a LINUX_REBOOT_CMD_RESTART2 with arg, say,
"psci-system-reset2-arch-warm-reset" it is pretty clear what it wants
to do in PSCI.

Again, it is a suggestion, comments welcome.

> yes we can move away from enum reboot_mode and use custom psci defines one -
> Ack.
> 
> > 
> 
> [snip ..]
> 
> > > > > +
> > > > > +/*
> > > > > + * arg1 is reset_type(Low 32 bit of magic).
> > > > > + * arg2 is cookie(High 32 bit of magic).
> > > > > + * If reset_type is 0, cookie will be used to decide the reset command.
> > > > > + */
> > > > > +static int psci_reboot_mode_write(struct reboot_mode_driver *reboot, u64 magic)
> > > > > +{
> > > > > +	u32 reset_type = REBOOT_MODE_ARG1(magic);
> > > > > +	u32 cookie = REBOOT_MODE_ARG2(magic);
> > > > > +
> > > > > +	if (reset_type == 0) {
> > > > > +		if (cookie == REBOOT_WARM || cookie == REBOOT_SOFT)
> > > > > +			psci_set_reset_cmd(true, 0, 0);
> > > > > +		else
> > > > > +			psci_set_reset_cmd(false, 0, 0);
> > > > > +	} else {
> > > > > +		psci_set_reset_cmd(true, reset_type, cookie);
> > > > > +	}
> > > > 
> > > > I don't think that psci_set_reset_cmd() has the right interface (and this
> > > > nested if is too complicated for my taste). All we need to pass is reset-type
> > > > and cookie (and if the reset is one of the predefined ones, reset-type is 0
> > > > and cookie is the REBOOT_* cookie).
> > > > 
> > > > Then the PSCI firmware driver will take the action according to what
> > > > resets are available.
> > > > 
> > > > How does it sound ?
> > > 
> > > So we mean these checks will move to the psci driver? Sorry for re-iterating
> > > the question.
> > 
> > Given what I say above, I believe that something we can do is mapping the magic
> > to an enum like:
> > 
> > PSCI_SYSTEM_RESET
> > PSCI_SYSTEM_RESET2_ARCH_SYSTEM_WARM_RESET
> > PSCI_SYSTEM_RESET2_VENDOR_RESET
> > 
> > and can add a probe function into PSCI driver similar to psci_has_osi_support() but
> > to probe for SYSTEM_RESET2 and initialize the predefined strings accordingly,
> > depending on its presence.
> 
> Not able to get it cleanly.
> 
> 1. Will move away from reboot_mode enum for pre-defined modes and define new
> enum defining these modes- fine.
> 2. get SYSTEM_RESET2 is supported from psci exported function -- fine, but
> how we use it here now, as we do not want to send the reset_cmd from
> psci_set_reset_cmd now?

You do keep psci_set_reset_cmd() but all it is used for is setting a struct
shared with the PSCI driver where you initialize the enum above, possibly
with a cookie if it is a vendor reset.

> 3. For pre-defined modes, warm/soft or cold - reset_type and cookie, both
> are zero, sys_reset2 or sys_reset2 decides the ARCH reset vs cold reset.
> 4. For vendor-rest , we use sys_reset2 with reset_type and cookie.

Yes.

> All above is done in reboot_notifier call at psci-reboot-mode.
> --
> 
> Now in the final restart_notifier->psci_sys_reset --
> 
> If panic is in progress, we do not use any of the cmd based reset params and
> go with the legacy reset. So we need to preserve the values that were set
> from psci-reboot-mode.
> 
> Did not understand the proposed suggestion in above usecase. Need more input
> on this.

I explained above. The reboot mode driver sets the command to carry out
depending on the string coming from user space and whether PSCI supports
SYSTEM_RESET2 or not.

> --
> 
> One other option is to have a restart_notifier in psci-reboot-mode, with
> lesser priority than psci_sys_rest and then handle all the case including
> panic and sys_reset2.

No.

Thanks,
Lorenzo


^ permalink raw reply

* Re: [PATCH net] net: airoha: Fix memory leak in airoha_qdma_rx_process()
From: Simon Horman @ 2026-04-03 15:59 UTC (permalink / raw)
  To: Lorenzo Bianconi
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, linux-arm-kernel, linux-mediatek, netdev
In-Reply-To: <20260402-airoha_qdma_rx_process-mem-leak-fix-v1-1-b5706f402d3c@kernel.org>

On Thu, Apr 02, 2026 at 02:57:10PM +0200, Lorenzo Bianconi wrote:
> If an error occurs on the subsequents buffers belonging to the
> non-linear part of the skb (e.g. due to an error in the payload length
> reported by the NIC or if we consumed all the available fragments for
> the skb), the page_pool fragment will not be linked to the skb so it will
> not return to the pool in the airoha_qdma_rx_process() error path. Fix the
> memory leak partially reverting commit 'd6d2b0e1538d ("net: airoha: Fix
> page recycling in airoha_qdma_rx_process()")' and always running
> page_pool_put_full_page routine in the airoha_qdma_rx_process() error
> path.
> 
> Fixes: d6d2b0e1538d ("net: airoha: Fix page recycling in airoha_qdma_rx_process()")
> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>

Reviewed-by: Simon Horman <horms@kernel.org>



^ permalink raw reply

* Re: [GIT PULL] ARM: dts: updates for ti/omap for v7.1
From: Kevin Hilman @ 2026-04-03 16:01 UTC (permalink / raw)
  To: Arnd Bergmann, soc; +Cc: Linux-OMAP, linux-arm-kernel
In-Reply-To: <83d0c8d8-fcde-4407-bb09-c2ae0e0e142d@app.fastmail.com>

"Arnd Bergmann" <arnd@arndb.de> writes:

> On Wed, Apr 1, 2026, at 23:29, Kevin Hilman wrote:
>>
>> ----------------------------------------------------------------
>> ARM: dts: updates for ti/omap for v7.1
>>
>
> Hi Kevin,
>
> I applied this one, but I noticed two problems:
>
> There is no long form changelog text, please add
> more information about what is in the branch in
> the future. I've added a short paragraph while
> applying.

Sorry about that, and thanks for fixing it up.

>> +-
>>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso-common.dtsi     | 744 
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso10.dts           | 101 
>> +++++++++++++++++++++
>>  arch/arm/boot/dts/ti/omap/omap4-samsung-espresso7.dts            |  70 
>> +++++++++++++++
>>  arch/arm/boot/dts/ti/omap/omap5-l4.dtsi                          |   2 
>
> Something went wrong with the overly long lines here.

Hmm, not sure what happened there.

Thanks,

Kevin


^ permalink raw reply

* Re: [PATCH bpf-next v12 1/5] bpf: Move constants blinding out of arch-specific JITs
From: Emil Tsalapatis @ 2026-04-03 16:04 UTC (permalink / raw)
  To: Xu Kuohai, bpf, linux-kernel, linux-arm-kernel
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Eduard Zingerman, Yonghong Song, Puranjay Mohan,
	Anton Protopopov, Alexis Lothoré, Shahab Vahedi,
	Russell King, Tiezhu Yang, Hengqi Chen, Johan Almbladh,
	Paul Burton, Hari Bathini, Christophe Leroy, Naveen N Rao,
	Luke Nelson, Xi Wang, Björn Töpel, Pu Lehui,
	Ilya Leoshkevich, Heiko Carstens, Vasily Gorbik, David S . Miller,
	Wang YanQing
In-Reply-To: <20260403132811.753894-2-xukuohai@huaweicloud.com>

On Fri Apr 3, 2026 at 9:28 AM EDT, Xu Kuohai wrote:
> From: Xu Kuohai <xukuohai@huawei.com>
>
> During the JIT stage, constants blinding rewrites instructions but only
> rewrites the private instruction copy of the JITed subprog, leaving the
> global env->prog->insni and env->insn_aux_data untouched. This causes a
> mismatch between subprog instructions and the global state, making it
> difficult to use the global data in the JIT.
>
> To avoid this mismatch, and given that all arch-specific JITs already
> support constants blinding, move it to the generic verifier code, and
> switch to rewrite the global env->prog->insnsi with the global states
> adjusted, as other rewrites in the verifier do.
>
> This removes the constants blinding calls in each JIT, which are largely
> duplicated code across architectures.
>
> Since constants blinding is only required for JIT, and there are two
> JIT entry functions, jit_subprogs() for BPF programs with multiple
> subprogs and bpf_prog_select_runtime() for programs with no subprogs,
> move the constants blinding invocation into these two functions.
>
> In the verifier path, bpf_patch_insn_data() is used to keep global
> verifier auxiliary data in sync with patched instructions. A key
> question is whether this global auxiliary data should be restored
> on the failure path.
>
> Besides instructions, bpf_patch_insn_data() adjusts:
>   - prog->aux->poke_tab
>   - env->insn_array_maps
>   - env->subprog_info
>   - env->insn_aux_data
>
> For prog->aux->poke_tab, it is only used by JIT or only meaningful after
> JIT succeeds, so it does not need to be restored on the failure path.
>
> For env->insn_array_maps, when JIT fails, programs using insn arrays
> are rejected by bpf_insn_array_ready() due to missing JIT addresses.
> Hence, env->insn_array_maps is only meaningful for JIT and does not need
> to be restored.
>
> For subprog_info, if jit_subprogs fails and CONFIG_BPF_JIT_ALWAYS_ON
> is not enabled, kernel falls back to interpreter. In this case,
> env->subprog_info is used to determine subprogram stack depth. So it
> must be restored on failure.
>
> For env->insn_aux_data, it is freed by clean_insn_aux_data() at the
> end of bpf_check(). Before freeing, clean_insn_aux_data() loops over
> env->insn_aux_data to release jump targets recorded in it. The loop
> uses env->prog->len as the array length, but this length no longer
> matches the actual size of the adjusted env->insn_aux_data array after
> constants blinding.
>
> To address it, a simple approach is to keep insn_aux_data as adjusted
> after failure, since it will be freed shortly, and record its actual size
> for the loop in clean_insn_aux_data(). But since clean_insn_aux_data()
> uses the same index to loop over both env->prog->insni and env->insn_aux_data,
> this approach result in incorrect index for the insni array. So an
> alternative approach is adopted: clone the original env->insn_aux_data
> before blinding and restore it after failure, similar to env->prog.
>
> For classic BPF programs, constants blinding works as before since it
> is still invoked from bpf_prog_select_runtime().
>
> Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com> # v8
> Reviewed-by: Hari Bathini <hbathini@linux.ibm.com> # powerpc jit
> Reviewed-by: Pu Lehui <pulehui@huawei.com> # riscv jit
> Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
> ---
>  arch/arc/net/bpf_jit_core.c      |  39 ++++-----
>  arch/arm/net/bpf_jit_32.c        |  41 ++--------
>  arch/arm64/net/bpf_jit_comp.c    |  72 +++++-----------
>  arch/loongarch/net/bpf_jit.c     |  59 ++++----------
>  arch/mips/net/bpf_jit_comp.c     |  20 +----
>  arch/parisc/net/bpf_jit_core.c   |  73 +++++++----------
>  arch/powerpc/net/bpf_jit_comp.c  |  68 ++++++----------
>  arch/riscv/net/bpf_jit_core.c    |  61 +++++---------
>  arch/s390/net/bpf_jit_comp.c     |  59 +++++---------
>  arch/sparc/net/bpf_jit_comp_64.c |  61 +++++---------
>  arch/x86/net/bpf_jit_comp.c      |  43 ++--------
>  arch/x86/net/bpf_jit_comp32.c    |  33 +-------
>  include/linux/filter.h           |  33 +++++++-
>  kernel/bpf/core.c                |  67 +++++++++++++--
>  kernel/bpf/verifier.c            | 136 +++++++++++++++++++++++++------
>  15 files changed, 390 insertions(+), 475 deletions(-)
>
> diff --git a/arch/arc/net/bpf_jit_core.c b/arch/arc/net/bpf_jit_core.c
> index 1421eeced0f5..973ceae48675 100644
> --- a/arch/arc/net/bpf_jit_core.c
> +++ b/arch/arc/net/bpf_jit_core.c
> @@ -79,7 +79,6 @@ struct arc_jit_data {
>   * The JIT pertinent context that is used by different functions.
>   *
>   * prog:		The current eBPF program being handled.
> - * orig_prog:		The original eBPF program before any possible change.
>   * jit:			The JIT buffer and its length.
>   * bpf_header:		The JITed program header. "jit.buf" points inside it.
>   * emit:		If set, opcodes are written to memory; else, a dry-run.
> @@ -94,12 +93,10 @@ struct arc_jit_data {
>   * need_extra_pass:	A forecast if an "extra_pass" will occur.
>   * is_extra_pass:	Indicates if the current pass is an extra pass.
>   * user_bpf_prog:	True, if VM opcodes come from a real program.
> - * blinded:		True if "constant blinding" step returned a new "prog".
>   * success:		Indicates if the whole JIT went OK.
>   */
>  struct jit_context {
>  	struct bpf_prog			*prog;
> -	struct bpf_prog			*orig_prog;
>  	struct jit_buffer		jit;
>  	struct bpf_binary_header	*bpf_header;
>  	bool				emit;
> @@ -114,7 +111,6 @@ struct jit_context {
>  	bool				need_extra_pass;
>  	bool				is_extra_pass;
>  	bool				user_bpf_prog;
> -	bool				blinded;
>  	bool				success;
>  };
>  
> @@ -161,13 +157,7 @@ static int jit_ctx_init(struct jit_context *ctx, struct bpf_prog *prog)
>  {
>  	memset(ctx, 0, sizeof(*ctx));
>  
> -	ctx->orig_prog = prog;
> -
> -	/* If constant blinding was requested but failed, scram. */
> -	ctx->prog = bpf_jit_blind_constants(prog);
> -	if (IS_ERR(ctx->prog))
> -		return PTR_ERR(ctx->prog);
> -	ctx->blinded = (ctx->prog != ctx->orig_prog);
> +	ctx->prog = prog;
>  
>  	/* If the verifier doesn't zero-extend, then we have to do it. */
>  	ctx->do_zext = !ctx->prog->aux->verifier_zext;
> @@ -214,14 +204,6 @@ static inline void maybe_free(struct jit_context *ctx, void **mem)
>   */
>  static void jit_ctx_cleanup(struct jit_context *ctx)
>  {
> -	if (ctx->blinded) {
> -		/* if all went well, release the orig_prog. */
> -		if (ctx->success)
> -			bpf_jit_prog_release_other(ctx->prog, ctx->orig_prog);
> -		else
> -			bpf_jit_prog_release_other(ctx->orig_prog, ctx->prog);
> -	}
> -
>  	maybe_free(ctx, (void **)&ctx->bpf2insn);
>  	maybe_free(ctx, (void **)&ctx->jit_data);
>  
> @@ -229,12 +211,19 @@ static void jit_ctx_cleanup(struct jit_context *ctx)
>  		ctx->bpf2insn_valid = false;
>  
>  	/* Freeing "bpf_header" is enough. "jit.buf" is a sub-array of it. */
> -	if (!ctx->success && ctx->bpf_header) {
> -		bpf_jit_binary_free(ctx->bpf_header);
> -		ctx->bpf_header = NULL;
> -		ctx->jit.buf    = NULL;
> -		ctx->jit.index  = 0;
> -		ctx->jit.len    = 0;
> +	if (!ctx->success) {
> +		if (ctx->bpf_header) {
> +			bpf_jit_binary_free(ctx->bpf_header);
> +			ctx->bpf_header = NULL;
> +			ctx->jit.buf    = NULL;
> +			ctx->jit.index  = 0;
> +			ctx->jit.len    = 0;
> +		}
> +		if (ctx->is_extra_pass) {
> +			ctx->prog->bpf_func = NULL;
> +			ctx->prog->jited = 0;
> +			ctx->prog->jited_len = 0;
> +		}
>  	}
>  
>  	ctx->emit = false;
> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
> index deeb8f292454..e6b1bb2de627 100644
> --- a/arch/arm/net/bpf_jit_32.c
> +++ b/arch/arm/net/bpf_jit_32.c
> @@ -2144,9 +2144,7 @@ bool bpf_jit_needs_zext(void)
>  
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	struct bpf_binary_header *header;
> -	bool tmp_blinded = false;
>  	struct jit_ctx ctx;
>  	unsigned int tmp_idx;
>  	unsigned int image_size;
> @@ -2156,20 +2154,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	 * the interpreter.
>  	 */
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	/* If constant blinding was enabled and we failed during blinding
> -	 * then we must fall back to the interpreter. Otherwise, we save
> -	 * the new JITed code.
> -	 */
> -	tmp = bpf_jit_blind_constants(prog);
> -
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	memset(&ctx, 0, sizeof(ctx));
>  	ctx.prog = prog;
> @@ -2179,10 +2164,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	 * we must fall back to the interpreter
>  	 */
>  	ctx.offsets = kcalloc(prog->len, sizeof(int), GFP_KERNEL);
> -	if (ctx.offsets == NULL) {
> -		prog = orig_prog;
> -		goto out;
> -	}
> +	if (ctx.offsets == NULL)
> +		return prog;
>  
>  	/* 1) fake pass to find in the length of the JITed code,
>  	 * to compute ctx->offsets and other context variables
> @@ -2194,10 +2177,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	 * being successful in the second pass, so just fall back
>  	 * to the interpreter.
>  	 */
> -	if (build_body(&ctx)) {
> -		prog = orig_prog;
> +	if (build_body(&ctx))
>  		goto out_off;
> -	}
>  
>  	tmp_idx = ctx.idx;
>  	build_prologue(&ctx);
> @@ -2213,10 +2194,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx.idx += ctx.imm_count;
>  	if (ctx.imm_count) {
>  		ctx.imms = kcalloc(ctx.imm_count, sizeof(u32), GFP_KERNEL);
> -		if (ctx.imms == NULL) {
> -			prog = orig_prog;
> +		if (ctx.imms == NULL)
>  			goto out_off;
> -		}
>  	}
>  #else
>  	/* there's nothing about the epilogue on ARMv7 */
> @@ -2238,10 +2217,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	/* Not able to allocate memory for the structure then
>  	 * we must fall back to the interpretation
>  	 */
> -	if (header == NULL) {
> -		prog = orig_prog;
> +	if (header == NULL)
>  		goto out_imms;
> -	}
>  
>  	/* 2.) Actual pass to generate final JIT code */
>  	ctx.target = (u32 *) image_ptr;
> @@ -2278,16 +2255,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  #endif
>  out_off:
>  	kfree(ctx.offsets);
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
> +
>  	return prog;
>  
>  out_free:
>  	image_ptr = NULL;
>  	bpf_jit_binary_free(header);
> -	prog = orig_prog;
>  	goto out_imms;
>  }
>  
> diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> index adf84962d579..cd5a72fff500 100644
> --- a/arch/arm64/net/bpf_jit_comp.c
> +++ b/arch/arm64/net/bpf_jit_comp.c
> @@ -2009,14 +2009,12 @@ struct arm64_jit_data {
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>  	int image_size, prog_size, extable_size, extable_align, extable_offset;
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	struct bpf_binary_header *header;
>  	struct bpf_binary_header *ro_header = NULL;
>  	struct arm64_jit_data *jit_data;
>  	void __percpu *priv_stack_ptr = NULL;
>  	bool was_classic = bpf_prog_was_classic(prog);
>  	int priv_stack_alloc_sz;
> -	bool tmp_blinded = false;
>  	bool extra_pass = false;
>  	struct jit_ctx ctx;
>  	u8 *image_ptr;
> @@ -2025,26 +2023,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	int exentry_idx;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	/* If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return prog;
>  		prog->aux->jit_data = jit_data;
>  	}
>  	priv_stack_ptr = prog->aux->priv_stack_ptr;
> @@ -2056,10 +2041,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 16) +
>  				      2 * PRIV_STACK_GUARD_SZ;
>  		priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_sz, 16, GFP_KERNEL);
> -		if (!priv_stack_ptr) {
> -			prog = orig_prog;
> +		if (!priv_stack_ptr)
>  			goto out_priv_stack;
> -		}
>  
>  		priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_sz);
>  		prog->aux->priv_stack_ptr = priv_stack_ptr;
> @@ -2079,10 +2062,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx.prog = prog;
>  
>  	ctx.offset = kvzalloc_objs(int, prog->len + 1);
> -	if (ctx.offset == NULL) {
> -		prog = orig_prog;
> +	if (ctx.offset == NULL)
>  		goto out_off;
> -	}
>  
>  	ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>  	ctx.arena_vm_start = bpf_arena_get_kern_vm_start(prog->aux->arena);
> @@ -2095,15 +2076,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	 * BPF line info needs ctx->offset[i] to be the offset of
>  	 * instruction[i] in jited image, so build prologue first.
>  	 */
> -	if (build_prologue(&ctx, was_classic)) {
> -		prog = orig_prog;
> +	if (build_prologue(&ctx, was_classic))
>  		goto out_off;
> -	}
>  
> -	if (build_body(&ctx, extra_pass)) {
> -		prog = orig_prog;
> +	if (build_body(&ctx, extra_pass))
>  		goto out_off;
> -	}
>  
>  	ctx.epilogue_offset = ctx.idx;
>  	build_epilogue(&ctx, was_classic);
> @@ -2121,10 +2098,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr,
>  					      sizeof(u64), &header, &image_ptr,
>  					      jit_fill_hole);
> -	if (!ro_header) {
> -		prog = orig_prog;
> +	if (!ro_header)
>  		goto out_off;
> -	}
>  
>  	/* Pass 2: Determine jited position and result for each instruction */
>  
> @@ -2152,10 +2127,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	/* Dont write body instructions to memory for now */
>  	ctx.write = false;
>  
> -	if (build_body(&ctx, extra_pass)) {
> -		prog = orig_prog;
> +	if (build_body(&ctx, extra_pass))
>  		goto out_free_hdr;
> -	}
>  
>  	ctx.epilogue_offset = ctx.idx;
>  	ctx.exentry_idx = exentry_idx;
> @@ -2164,19 +2137,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  
>  	/* Pass 3: Adjust jump offset and write final image */
>  	if (build_body(&ctx, extra_pass) ||
> -		WARN_ON_ONCE(ctx.idx != ctx.epilogue_offset)) {
> -		prog = orig_prog;
> +		WARN_ON_ONCE(ctx.idx != ctx.epilogue_offset))

This thunk is slightly different now, the WARN_ON_ONCE() won't be checked
if build_body() succeeds. Do we even need it? AFAICT the only case it
wouldn't trigger if build_body() fails is if it did so at the very last
instruction. Alternatively, should we check it if build_body() succeeds
instead to retain the old behavior?

>  		goto out_free_hdr;
> -	}
>  
>  	build_epilogue(&ctx, was_classic);
>  	build_plt(&ctx);
>  
>  	/* Extra pass to validate JITed code. */
> -	if (validate_ctx(&ctx)) {
> -		prog = orig_prog;
> +	if (validate_ctx(&ctx))
>  		goto out_free_hdr;
> -	}
>  
>  	/* update the real prog size */
>  	prog_size = sizeof(u32) * ctx.idx;
> @@ -2193,16 +2162,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		if (extra_pass && ctx.idx > jit_data->ctx.idx) {
>  			pr_err_once("multi-func JIT bug %d > %d\n",
>  				    ctx.idx, jit_data->ctx.idx);
> -			prog->bpf_func = NULL;
> -			prog->jited = 0;
> -			prog->jited_len = 0;
>  			goto out_free_hdr;
>  		}
>  		if (WARN_ON(bpf_jit_binary_pack_finalize(ro_header, header))) {
> -			/* ro_header has been freed */
> +			/* ro_header and header has been freed */
>  			ro_header = NULL;
> -			prog = orig_prog;
> -			goto out_off;
> +			header = NULL;
> +			goto out_free_hdr;
>  		}
>  		/*
>  		 * The instructions have now been copied to the ROX region from
> @@ -2245,13 +2211,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		kfree(jit_data);
>  		prog->aux->jit_data = NULL;
>  	}
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
> +
>  	return prog;
>  
>  out_free_hdr:
> +	if (extra_pass) {
> +		prog->bpf_func = NULL;
> +		prog->jited = 0;
> +		prog->jited_len = 0;
> +	}
>  	if (header) {
>  		bpf_arch_text_copy(&ro_header->size, &header->size,
>  				   sizeof(header->size));
> diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
> index 9cb796e16379..fcc8c0c29fb0 100644
> --- a/arch/loongarch/net/bpf_jit.c
> +++ b/arch/loongarch/net/bpf_jit.c
> @@ -1922,43 +1922,26 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
>  
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -	bool tmp_blinded = false, extra_pass = false;
> +	bool extra_pass = false;
>  	u8 *image_ptr, *ro_image_ptr;
>  	int image_size, prog_size, extable_size;
>  	struct jit_ctx ctx;
>  	struct jit_data *jit_data;
>  	struct bpf_binary_header *header;
>  	struct bpf_binary_header *ro_header;
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  
>  	/*
>  	 * If BPF JIT was not enabled then we must fall back to
>  	 * the interpreter.
>  	 */
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	/*
> -	 * If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter. Otherwise, we save
> -	 * the new JITed code.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return prog;
>  		prog->aux->jit_data = jit_data;
>  	}
>  	if (jit_data->ctx.offset) {
> @@ -1978,17 +1961,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx.user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>  
>  	ctx.offset = kvcalloc(prog->len + 1, sizeof(u32), GFP_KERNEL);
> -	if (ctx.offset == NULL) {
> -		prog = orig_prog;
> +	if (ctx.offset == NULL)
>  		goto out_offset;
> -	}
>  
>  	/* 1. Initial fake pass to compute ctx->idx and set ctx->flags */
>  	build_prologue(&ctx);
> -	if (build_body(&ctx, extra_pass)) {
> -		prog = orig_prog;
> +	if (build_body(&ctx, extra_pass))
>  		goto out_offset;
> -	}
>  	ctx.epilogue_offset = ctx.idx;
>  	build_epilogue(&ctx);
>  
> @@ -2004,10 +1983,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	/* Now we know the size of the structure to make */
>  	ro_header = bpf_jit_binary_pack_alloc(image_size, &ro_image_ptr, sizeof(u32),
>  					      &header, &image_ptr, jit_fill_hole);
> -	if (!ro_header) {
> -		prog = orig_prog;
> +	if (!ro_header)
>  		goto out_offset;
> -	}
>  
>  	/* 2. Now, the actual pass to generate final JIT code */
>  	/*
> @@ -2027,17 +2004,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx.num_exentries = 0;
>  
>  	build_prologue(&ctx);
> -	if (build_body(&ctx, extra_pass)) {
> -		prog = orig_prog;
> +	if (build_body(&ctx, extra_pass))
>  		goto out_free;
> -	}
>  	build_epilogue(&ctx);
>  
>  	/* 3. Extra pass to validate JITed code */
> -	if (validate_ctx(&ctx)) {
> -		prog = orig_prog;
> +	if (validate_ctx(&ctx))
>  		goto out_free;
> -	}
>  
>  	/* And we're done */
>  	if (bpf_jit_enable > 1)
> @@ -2050,9 +2023,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  			goto out_free;
>  		}
>  		if (WARN_ON(bpf_jit_binary_pack_finalize(ro_header, header))) {
> -			/* ro_header has been freed */
> +			/* ro_header and header have been freed */
>  			ro_header = NULL;
> -			prog = orig_prog;
> +			header = NULL;
>  			goto out_free;
>  		}
>  		/*
> @@ -2084,13 +2057,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		prog->aux->jit_data = NULL;
>  	}
>  
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ? tmp : orig_prog);
> -
>  	return prog;
>  
>  out_free:
> +	if (extra_pass) {
> +		prog->bpf_func = NULL;
> +		prog->jited = 0;
> +		prog->jited_len = 0;
> +	}
> +
>  	if (header) {
>  		bpf_arch_text_copy(&ro_header->size, &header->size, sizeof(header->size));
>  		bpf_jit_binary_pack_free(ro_header, header);
> diff --git a/arch/mips/net/bpf_jit_comp.c b/arch/mips/net/bpf_jit_comp.c
> index e355dfca4400..d2b6c955f18e 100644
> --- a/arch/mips/net/bpf_jit_comp.c
> +++ b/arch/mips/net/bpf_jit_comp.c
> @@ -911,10 +911,8 @@ bool bpf_jit_needs_zext(void)
>  
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	struct bpf_binary_header *header = NULL;
>  	struct jit_context ctx;
> -	bool tmp_blinded = false;
>  	unsigned int tmp_idx;
>  	unsigned int image_size;
>  	u8 *image_ptr;
> @@ -925,19 +923,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	 * the interpreter.
>  	 */
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -	/*
> -	 * If constant blinding was enabled and we failed during blinding
> -	 * then we must fall back to the interpreter. Otherwise, we save
> -	 * the new JITed code.
> -	 */
> -	tmp = bpf_jit_blind_constants(prog);
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	memset(&ctx, 0, sizeof(ctx));
>  	ctx.program = prog;
> @@ -1025,14 +1011,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	prog->jited_len = image_size;
>  
>  out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
>  	kfree(ctx.descriptors);
>  	return prog;
>  
>  out_err:
> -	prog = orig_prog;
>  	if (header)
>  		bpf_jit_binary_free(header);
>  	goto out;
> diff --git a/arch/parisc/net/bpf_jit_core.c b/arch/parisc/net/bpf_jit_core.c
> index a5eb6b51e27a..35dca372b5df 100644
> --- a/arch/parisc/net/bpf_jit_core.c
> +++ b/arch/parisc/net/bpf_jit_core.c
> @@ -44,30 +44,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>  	unsigned int prog_size = 0, extable_size = 0;
> -	bool tmp_blinded = false, extra_pass = false;
> -	struct bpf_prog *tmp, *orig_prog = prog;
> +	bool extra_pass = false;
>  	int pass = 0, prev_ninsns = 0, prologue_len, i;
>  	struct hppa_jit_data *jit_data;
>  	struct hppa_jit_context *ctx;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return prog;
>  		prog->aux->jit_data = jit_data;
>  	}
>  
> @@ -81,10 +70,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  
>  	ctx->prog = prog;
>  	ctx->offset = kzalloc_objs(int, prog->len);
> -	if (!ctx->offset) {
> -		prog = orig_prog;
> -		goto out_offset;
> -	}
> +	if (!ctx->offset)
> +		goto out_err;
>  	for (i = 0; i < prog->len; i++) {
>  		prev_ninsns += 20;
>  		ctx->offset[i] = prev_ninsns;
> @@ -93,10 +80,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	for (i = 0; i < NR_JIT_ITERATIONS; i++) {
>  		pass++;
>  		ctx->ninsns = 0;
> -		if (build_body(ctx, extra_pass, ctx->offset)) {
> -			prog = orig_prog;
> -			goto out_offset;
> -		}
> +		if (build_body(ctx, extra_pass, ctx->offset))
> +			goto out_err;
>  		ctx->body_len = ctx->ninsns;
>  		bpf_jit_build_prologue(ctx);
>  		ctx->prologue_len = ctx->ninsns - ctx->body_len;
> @@ -116,10 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  						     &jit_data->image,
>  						     sizeof(long),
>  						     bpf_fill_ill_insns);
> -			if (!jit_data->header) {
> -				prog = orig_prog;
> -				goto out_offset;
> -			}
> +			if (!jit_data->header)
> +				goto out_err;
>  
>  			ctx->insns = (u32 *)jit_data->image;
>  			/*
> @@ -134,8 +117,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
>  		if (jit_data->header)
>  			bpf_jit_binary_free(jit_data->header);
> -		prog = orig_prog;
> -		goto out_offset;
> +		goto out_err;
>  	}
>  
>  	if (extable_size)
> @@ -148,8 +130,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	bpf_jit_build_prologue(ctx);
>  	if (build_body(ctx, extra_pass, NULL)) {
>  		bpf_jit_binary_free(jit_data->header);
> -		prog = orig_prog;
> -		goto out_offset;
> +		goto out_err;
>  	}
>  	bpf_jit_build_epilogue(ctx);
>  
> @@ -160,20 +141,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  			{ extern int machine_restart(char *); machine_restart(""); }
>  	}
>  
> +	if (!prog->is_func || extra_pass) {
> +		if (bpf_jit_binary_lock_ro(jit_data->header)) {
> +			bpf_jit_binary_free(jit_data->header);
> +			goto out_err;
> +		}
> +		bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
> +	}
> +
>  	prog->bpf_func = (void *)ctx->insns;
>  	prog->jited = 1;
>  	prog->jited_len = prog_size;
>  
> -	bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);
> -
>  	if (!prog->is_func || extra_pass) {
> -		if (bpf_jit_binary_lock_ro(jit_data->header)) {
> -			bpf_jit_binary_free(jit_data->header);
> -			prog->bpf_func = NULL;
> -			prog->jited = 0;
> -			prog->jited_len = 0;
> -			goto out_offset;
> -		}
>  		prologue_len = ctx->epilogue_offset - ctx->body_len;
>  		for (i = 0; i < prog->len; i++)
>  			ctx->offset[i] += prologue_len;
> @@ -183,14 +163,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		kfree(jit_data);
>  		prog->aux->jit_data = NULL;
>  	}
> -out:
> +
>  	if (HPPA_JIT_REBOOT)
>  		{ extern int machine_restart(char *); machine_restart(""); }
>  
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
>  	return prog;
> +
> +out_err:
> +	if (extra_pass) {
> +		prog->bpf_func = NULL;
> +		prog->jited = 0;
> +		prog->jited_len = 0;
> +	}
> +	goto out_offset;
>  }
>  
>  u64 hppa_div64(u64 div, u64 divisor)
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index a62a9a92b7b5..711028bebea3 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -142,9 +142,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	int flen;
>  	struct bpf_binary_header *fhdr = NULL;
>  	struct bpf_binary_header *hdr = NULL;
> -	struct bpf_prog *org_fp = fp;
> -	struct bpf_prog *tmp_fp;
> -	bool bpf_blinded = false;
>  	bool extra_pass = false;
>  	u8 *fimage = NULL;
>  	u32 *fcode_base;
> @@ -152,24 +149,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	u32 fixup_len;
>  
>  	if (!fp->jit_requested)
> -		return org_fp;
> -
> -	tmp_fp = bpf_jit_blind_constants(org_fp);
> -	if (IS_ERR(tmp_fp))
> -		return org_fp;
> -
> -	if (tmp_fp != org_fp) {
> -		bpf_blinded = true;
> -		fp = tmp_fp;
> -	}
> +		return fp;
>  
>  	jit_data = fp->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			fp = org_fp;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return fp;
>  		fp->aux->jit_data = jit_data;
>  	}
>  
> @@ -194,10 +180,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	}
>  
>  	addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL);
> -	if (addrs == NULL) {
> -		fp = org_fp;
> -		goto out_addrs;
> -	}
> +	if (addrs == NULL)
> +		goto out_err;
>  
>  	memset(&cgctx, 0, sizeof(struct codegen_context));
>  	bpf_jit_init_reg_mapping(&cgctx);
> @@ -211,11 +195,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	cgctx.exception_cb = fp->aux->exception_cb;
>  
>  	/* Scouting faux-generate pass 0 */
> -	if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
> +	if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false))
>  		/* We hit something illegal or unsupported. */
> -		fp = org_fp;
> -		goto out_addrs;
> -	}
> +		goto out_err;
>  
>  	/*
>  	 * If we have seen a tail call, we need a second pass.
> @@ -226,10 +208,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	 */
>  	if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) {
>  		cgctx.idx = 0;
> -		if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false)) {
> -			fp = org_fp;
> -			goto out_addrs;
> -		}
> +		if (bpf_jit_build_body(fp, NULL, NULL, &cgctx, addrs, 0, false))
> +			goto out_err;
>  	}
>  
>  	bpf_jit_realloc_regs(&cgctx);
> @@ -250,10 +230,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  
>  	fhdr = bpf_jit_binary_pack_alloc(alloclen, &fimage, 4, &hdr, &image,
>  					      bpf_jit_fill_ill_insns);
> -	if (!fhdr) {
> -		fp = org_fp;
> -		goto out_addrs;
> -	}
> +	if (!fhdr)
> +		goto out_err;
>  
>  	if (extable_len)
>  		fp->aux->extable = (void *)fimage + FUNCTION_DESCR_SIZE + proglen + fixup_len;
> @@ -272,8 +250,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  				       extra_pass)) {
>  			bpf_arch_text_copy(&fhdr->size, &hdr->size, sizeof(hdr->size));
>  			bpf_jit_binary_pack_free(fhdr, hdr);
> -			fp = org_fp;
> -			goto out_addrs;
> +			goto out_err;
>  		}
>  		bpf_jit_build_epilogue(code_base, &cgctx);
>  
> @@ -295,15 +272,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	((u64 *)image)[1] = local_paca->kernel_toc;
>  #endif
>  
> +	if (!fp->is_func || extra_pass) {
> +		if (bpf_jit_binary_pack_finalize(fhdr, hdr))
> +			goto out_err;
> +	}
> +
>  	fp->bpf_func = (void *)fimage;
>  	fp->jited = 1;
>  	fp->jited_len = cgctx.idx * 4 + FUNCTION_DESCR_SIZE;
>  
>  	if (!fp->is_func || extra_pass) {
> -		if (bpf_jit_binary_pack_finalize(fhdr, hdr)) {
> -			fp = org_fp;
> -			goto out_addrs;
> -		}
>  		bpf_prog_fill_jited_linfo(fp, addrs);
>  out_addrs:
>  		kfree(addrs);
> @@ -318,11 +296,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  		jit_data->hdr = hdr;
>  	}
>  
> -out:
> -	if (bpf_blinded)
> -		bpf_jit_prog_release_other(fp, fp == org_fp ? tmp_fp : org_fp);
> -
>  	return fp;
> +
> +out_err:
> +	if (extra_pass) {
> +		fp->bpf_func = NULL;
> +		fp->jited = 0;
> +		fp->jited_len = 0;
> +	}
> +	goto out_addrs;
>  }
>  
>  /*
> diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
> index b3581e926436..527baa50dc68 100644
> --- a/arch/riscv/net/bpf_jit_core.c
> +++ b/arch/riscv/net/bpf_jit_core.c
> @@ -44,29 +44,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>  	unsigned int prog_size = 0, extable_size = 0;
> -	bool tmp_blinded = false, extra_pass = false;
> -	struct bpf_prog *tmp, *orig_prog = prog;
> +	bool extra_pass = false;
>  	int pass = 0, prev_ninsns = 0, i;
>  	struct rv_jit_data *jit_data;
>  	struct rv_jit_context *ctx;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
>  		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> +			return prog;
>  		}
>  		prog->aux->jit_data = jit_data;
>  	}
> @@ -83,15 +73,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx->user_vm_start = bpf_arena_get_user_vm_start(prog->aux->arena);
>  	ctx->prog = prog;
>  	ctx->offset = kzalloc_objs(int, prog->len);
> -	if (!ctx->offset) {
> -		prog = orig_prog;
> +	if (!ctx->offset)
>  		goto out_offset;
> -	}
>  
> -	if (build_body(ctx, extra_pass, NULL)) {
> -		prog = orig_prog;
> +	if (build_body(ctx, extra_pass, NULL))
>  		goto out_offset;
> -	}
>  
>  	for (i = 0; i < prog->len; i++) {
>  		prev_ninsns += 32;
> @@ -105,10 +91,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		bpf_jit_build_prologue(ctx, bpf_is_subprog(prog));
>  		ctx->prologue_len = ctx->ninsns;
>  
> -		if (build_body(ctx, extra_pass, ctx->offset)) {
> -			prog = orig_prog;
> +		if (build_body(ctx, extra_pass, ctx->offset))
>  			goto out_offset;
> -		}
>  
>  		ctx->epilogue_offset = ctx->ninsns;
>  		bpf_jit_build_epilogue(ctx);
> @@ -126,10 +110,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  							  &jit_data->ro_image, sizeof(u32),
>  							  &jit_data->header, &jit_data->image,
>  							  bpf_fill_ill_insns);
> -			if (!jit_data->ro_header) {
> -				prog = orig_prog;
> +			if (!jit_data->ro_header)
>  				goto out_offset;
> -			}
>  
>  			/*
>  			 * Use the image(RW) for writing the JITed instructions. But also save
> @@ -150,7 +132,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  
>  	if (i == NR_JIT_ITERATIONS) {
>  		pr_err("bpf-jit: image did not converge in <%d passes!\n", i);
> -		prog = orig_prog;
>  		goto out_free_hdr;
>  	}
>  
> @@ -163,26 +144,27 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx->nexentries = 0;
>  
>  	bpf_jit_build_prologue(ctx, bpf_is_subprog(prog));
> -	if (build_body(ctx, extra_pass, NULL)) {
> -		prog = orig_prog;
> +	if (build_body(ctx, extra_pass, NULL))
>  		goto out_free_hdr;
> -	}
>  	bpf_jit_build_epilogue(ctx);
>  
>  	if (bpf_jit_enable > 1)
>  		bpf_jit_dump(prog->len, prog_size, pass, ctx->insns);
>  
> -	prog->bpf_func = (void *)ctx->ro_insns + cfi_get_offset();
> -	prog->jited = 1;
> -	prog->jited_len = prog_size - cfi_get_offset();
> -
>  	if (!prog->is_func || extra_pass) {
>  		if (WARN_ON(bpf_jit_binary_pack_finalize(jit_data->ro_header, jit_data->header))) {
>  			/* ro_header has been freed */
>  			jit_data->ro_header = NULL;
> -			prog = orig_prog;
> -			goto out_offset;
> +			jit_data->header = NULL;
> +			goto out_free_hdr;
>  		}
> +	}
> +
> +	prog->bpf_func = (void *)ctx->ro_insns + cfi_get_offset();
> +	prog->jited = 1;
> +	prog->jited_len = prog_size - cfi_get_offset();
> +
> +	if (!prog->is_func || extra_pass) {
>  		/*
>  		 * The instructions have now been copied to the ROX region from
>  		 * where they will execute.
> @@ -198,14 +180,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		kfree(jit_data);
>  		prog->aux->jit_data = NULL;
>  	}
> -out:
>  
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
>  	return prog;
>  
>  out_free_hdr:
> +	if (extra_pass) {
> +		prog->bpf_func = NULL;
> +		prog->jited = 0;
> +		prog->jited_len = 0;
> +	}
>  	if (jit_data->header) {
>  		bpf_arch_text_copy(&jit_data->ro_header->size, &jit_data->header->size,
>  				   sizeof(jit_data->header->size));
> diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
> index d08d159b6319..2dfc279b1be2 100644
> --- a/arch/s390/net/bpf_jit_comp.c
> +++ b/arch/s390/net/bpf_jit_comp.c
> @@ -2314,36 +2314,20 @@ static struct bpf_binary_header *bpf_jit_alloc(struct bpf_jit *jit,
>   */
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  {
> -	struct bpf_prog *tmp, *orig_fp = fp;
>  	struct bpf_binary_header *header;
>  	struct s390_jit_data *jit_data;
> -	bool tmp_blinded = false;
>  	bool extra_pass = false;
>  	struct bpf_jit jit;
>  	int pass;
>  
>  	if (!fp->jit_requested)
> -		return orig_fp;
> -
> -	tmp = bpf_jit_blind_constants(fp);
> -	/*
> -	 * If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_fp;
> -	if (tmp != fp) {
> -		tmp_blinded = true;
> -		fp = tmp;
> -	}
> +		return fp;
>  
>  	jit_data = fp->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			fp = orig_fp;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return fp;
>  		fp->aux->jit_data = jit_data;
>  	}
>  	if (jit_data->ctx.addrs) {
> @@ -2356,34 +2340,27 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  
>  	memset(&jit, 0, sizeof(jit));
>  	jit.addrs = kvcalloc(fp->len + 1, sizeof(*jit.addrs), GFP_KERNEL);
> -	if (jit.addrs == NULL) {
> -		fp = orig_fp;
> -		goto free_addrs;
> -	}
> +	if (jit.addrs == NULL)
> +		goto out_err;
>  	/*
>  	 * Three initial passes:
>  	 *   - 1/2: Determine clobbered registers
>  	 *   - 3:   Calculate program size and addrs array
>  	 */
>  	for (pass = 1; pass <= 3; pass++) {
> -		if (bpf_jit_prog(&jit, fp, extra_pass)) {
> -			fp = orig_fp;
> -			goto free_addrs;
> -		}
> +		if (bpf_jit_prog(&jit, fp, extra_pass))
> +			goto out_err;
>  	}
>  	/*
>  	 * Final pass: Allocate and generate program
>  	 */
>  	header = bpf_jit_alloc(&jit, fp);
> -	if (!header) {
> -		fp = orig_fp;
> -		goto free_addrs;
> -	}
> +	if (!header)
> +		goto out_err;
>  skip_init_ctx:
>  	if (bpf_jit_prog(&jit, fp, extra_pass)) {
>  		bpf_jit_binary_free(header);
> -		fp = orig_fp;
> -		goto free_addrs;
> +		goto out_err;
>  	}
>  	if (bpf_jit_enable > 1) {
>  		bpf_jit_dump(fp->len, jit.size, pass, jit.prg_buf);
> @@ -2392,8 +2369,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  	if (!fp->is_func || extra_pass) {
>  		if (bpf_jit_binary_lock_ro(header)) {
>  			bpf_jit_binary_free(header);
> -			fp = orig_fp;
> -			goto free_addrs;
> +			goto out_err;
>  		}
>  	} else {
>  		jit_data->header = header;
> @@ -2411,11 +2387,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>  		kfree(jit_data);
>  		fp->aux->jit_data = NULL;
>  	}
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(fp, fp == orig_fp ?
> -					   tmp : orig_fp);
> +
>  	return fp;
> +
> +out_err:
> +	if (extra_pass) {
> +		fp->bpf_func = NULL;
> +		fp->jited = 0;
> +		fp->jited_len = 0;
> +	}
> +	goto free_addrs;
>  }
>  
>  bool bpf_jit_supports_kfunc_call(void)
> diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c
> index b23d1c645ae5..e83e29137566 100644
> --- a/arch/sparc/net/bpf_jit_comp_64.c
> +++ b/arch/sparc/net/bpf_jit_comp_64.c
> @@ -1479,37 +1479,22 @@ struct sparc64_jit_data {
>  
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	struct sparc64_jit_data *jit_data;
>  	struct bpf_binary_header *header;
>  	u32 prev_image_size, image_size;
> -	bool tmp_blinded = false;
>  	bool extra_pass = false;
>  	struct jit_ctx ctx;
>  	u8 *image_ptr;
>  	int pass, i;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	/* If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return prog;
>  		prog->aux->jit_data = jit_data;
>  	}
>  	if (jit_data->ctx.offset) {
> @@ -1527,10 +1512,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	ctx.prog = prog;
>  
>  	ctx.offset = kmalloc_array(prog->len, sizeof(unsigned int), GFP_KERNEL);
> -	if (ctx.offset == NULL) {
> -		prog = orig_prog;
> -		goto out_off;
> -	}
> +	if (ctx.offset == NULL)
> +		goto out_err;
>  
>  	/* Longest sequence emitted is for bswap32, 12 instructions.  Pre-cook
>  	 * the offset array so that we converge faster.
> @@ -1543,10 +1526,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		ctx.idx = 0;
>  
>  		build_prologue(&ctx);
> -		if (build_body(&ctx)) {
> -			prog = orig_prog;
> -			goto out_off;
> -		}
> +		if (build_body(&ctx))
> +			goto out_err;
>  		build_epilogue(&ctx);
>  
>  		if (bpf_jit_enable > 1)
> @@ -1569,10 +1550,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	image_size = sizeof(u32) * ctx.idx;
>  	header = bpf_jit_binary_alloc(image_size, &image_ptr,
>  				      sizeof(u32), jit_fill_hole);
> -	if (header == NULL) {
> -		prog = orig_prog;
> -		goto out_off;
> -	}
> +	if (header == NULL)
> +		goto out_err;
>  
>  	ctx.image = (u32 *)image_ptr;
>  skip_init_ctx:
> @@ -1582,8 +1561,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  
>  	if (build_body(&ctx)) {
>  		bpf_jit_binary_free(header);
> -		prog = orig_prog;
> -		goto out_off;
> +		goto out_err;
>  	}
>  
>  	build_epilogue(&ctx);
> @@ -1592,8 +1570,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		pr_err("bpf_jit: Failed to converge, prev_size=%u size=%d\n",
>  		       prev_image_size, ctx.idx * 4);
>  		bpf_jit_binary_free(header);
> -		prog = orig_prog;
> -		goto out_off;
> +		goto out_err;
>  	}
>  
>  	if (bpf_jit_enable > 1)
> @@ -1604,8 +1581,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	if (!prog->is_func || extra_pass) {
>  		if (bpf_jit_binary_lock_ro(header)) {
>  			bpf_jit_binary_free(header);
> -			prog = orig_prog;
> -			goto out_off;
> +			goto out_err;
>  		}
>  	} else {
>  		jit_data->ctx = ctx;
> @@ -1624,9 +1600,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		kfree(jit_data);
>  		prog->aux->jit_data = NULL;
>  	}
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
> +
>  	return prog;
> +
> +out_err:
> +	if (extra_pass) {
> +		prog->bpf_func = NULL;
> +		prog->jited = 0;
> +		prog->jited_len = 0;
> +	}
> +	goto out_off;
>  }
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index e9b78040d703..77d00a8dec87 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -3717,13 +3717,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *rw_header = NULL;
>  	struct bpf_binary_header *header = NULL;
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	void __percpu *priv_stack_ptr = NULL;
>  	struct x64_jit_data *jit_data;
>  	int priv_stack_alloc_sz;
>  	int proglen, oldproglen = 0;
>  	struct jit_context ctx = {};
> -	bool tmp_blinded = false;
>  	bool extra_pass = false;
>  	bool padding = false;
>  	u8 *rw_image = NULL;
> @@ -3733,27 +3731,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  	int i;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	/*
> -	 * If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	jit_data = prog->aux->jit_data;
>  	if (!jit_data) {
>  		jit_data = kzalloc_obj(*jit_data);
> -		if (!jit_data) {
> -			prog = orig_prog;
> -			goto out;
> -		}
> +		if (!jit_data)
> +			return prog;
>  		prog->aux->jit_data = jit_data;
>  	}
>  	priv_stack_ptr = prog->aux->priv_stack_ptr;
> @@ -3765,10 +3749,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		priv_stack_alloc_sz = round_up(prog->aux->stack_depth, 8) +
>  				      2 * PRIV_STACK_GUARD_SZ;
>  		priv_stack_ptr = __alloc_percpu_gfp(priv_stack_alloc_sz, 8, GFP_KERNEL);
> -		if (!priv_stack_ptr) {
> -			prog = orig_prog;
> +		if (!priv_stack_ptr)
>  			goto out_priv_stack;
> -		}
>  
>  		priv_stack_init_guard(priv_stack_ptr, priv_stack_alloc_sz);
>  		prog->aux->priv_stack_ptr = priv_stack_ptr;
> @@ -3786,10 +3768,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		goto skip_init_addrs;
>  	}
>  	addrs = kvmalloc_objs(*addrs, prog->len + 1);
> -	if (!addrs) {
> -		prog = orig_prog;
> +	if (!addrs)
>  		goto out_addrs;
> -	}
>  
>  	/*
>  	 * Before first pass, make a rough estimation of addrs[]
> @@ -3820,8 +3800,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  						   sizeof(rw_header->size));
>  				bpf_jit_binary_pack_free(header, rw_header);
>  			}
> -			/* Fall back to interpreter mode */
> -			prog = orig_prog;
>  			if (extra_pass) {
>  				prog->bpf_func = NULL;
>  				prog->jited = 0;
> @@ -3852,10 +3830,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  			header = bpf_jit_binary_pack_alloc(roundup(proglen, align) + extable_size,
>  							   &image, align, &rw_header, &rw_image,
>  							   jit_fill_hole);
> -			if (!header) {
> -				prog = orig_prog;
> +			if (!header)
>  				goto out_addrs;
> -			}
>  			prog->aux->extable = (void *) image + roundup(proglen, align);
>  		}
>  		oldproglen = proglen;
> @@ -3908,8 +3884,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		prog->bpf_func = (void *)image + cfi_get_offset();
>  		prog->jited = 1;
>  		prog->jited_len = proglen - cfi_get_offset();
> -	} else {
> -		prog = orig_prog;
>  	}
>  
>  	if (!image || !prog->is_func || extra_pass) {
> @@ -3925,10 +3899,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		kfree(jit_data);
>  		prog->aux->jit_data = NULL;
>  	}
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
> +
>  	return prog;
>  }
>  
> diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
> index dda423025c3d..5f259577614a 100644
> --- a/arch/x86/net/bpf_jit_comp32.c
> +++ b/arch/x86/net/bpf_jit_comp32.c
> @@ -2521,35 +2521,19 @@ bool bpf_jit_needs_zext(void)
>  struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *header = NULL;
> -	struct bpf_prog *tmp, *orig_prog = prog;
>  	int proglen, oldproglen = 0;
>  	struct jit_context ctx = {};
> -	bool tmp_blinded = false;
>  	u8 *image = NULL;
>  	int *addrs;
>  	int pass;
>  	int i;
>  
>  	if (!prog->jit_requested)
> -		return orig_prog;
> -
> -	tmp = bpf_jit_blind_constants(prog);
> -	/*
> -	 * If blinding was requested and we failed during blinding,
> -	 * we must fall back to the interpreter.
> -	 */
> -	if (IS_ERR(tmp))
> -		return orig_prog;
> -	if (tmp != prog) {
> -		tmp_blinded = true;
> -		prog = tmp;
> -	}
> +		return prog;
>  
>  	addrs = kmalloc_objs(*addrs, prog->len);
> -	if (!addrs) {
> -		prog = orig_prog;
> -		goto out;
> -	}
> +	if (!addrs)
> +		return prog;
>  
>  	/*
>  	 * Before first pass, make a rough estimation of addrs[]
> @@ -2574,7 +2558,6 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  			image = NULL;
>  			if (header)
>  				bpf_jit_binary_free(header);
> -			prog = orig_prog;
>  			goto out_addrs;
>  		}
>  		if (image) {
> @@ -2588,10 +2571,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		if (proglen == oldproglen) {
>  			header = bpf_jit_binary_alloc(proglen, &image,
>  						      1, jit_fill_hole);
> -			if (!header) {
> -				prog = orig_prog;
> +			if (!header)
>  				goto out_addrs;
> -			}
>  		}
>  		oldproglen = proglen;
>  		cond_resched();
> @@ -2604,16 +2585,10 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
>  		prog->bpf_func = (void *)image;
>  		prog->jited = 1;
>  		prog->jited_len = proglen;
> -	} else {
> -		prog = orig_prog;
>  	}
>  
>  out_addrs:
>  	kfree(addrs);
> -out:
> -	if (tmp_blinded)
> -		bpf_jit_prog_release_other(prog, prog == orig_prog ?
> -					   tmp : orig_prog);
>  	return prog;
>  }
>  
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index e40d4071a345..d396e55c9a1d 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -1183,6 +1183,18 @@ static inline bool bpf_dump_raw_ok(const struct cred *cred)
>  
>  struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
>  				       const struct bpf_insn *patch, u32 len);
> +
> +#ifdef CONFIG_BPF_SYSCALL
> +struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +				     const struct bpf_insn *patch, u32 len);
> +#else
> +static inline struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +						   const struct bpf_insn *patch, u32 len)
> +{
> +	return ERR_PTR(-ENOTSUPP);
> +}
> +#endif /* CONFIG_BPF_SYSCALL */
> +
>  int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
>  
>  static inline bool xdp_return_frame_no_direct(void)
> @@ -1309,9 +1321,14 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog,
>  
>  const char *bpf_jit_get_prog_name(struct bpf_prog *prog);
>  
> -struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *fp);
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog);
>  void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other);
>  
> +static inline bool bpf_prog_need_blind(const struct bpf_prog *prog)
> +{
> +	return prog->blinding_requested && !prog->blinded;
> +}
> +
>  static inline void bpf_jit_dump(unsigned int flen, unsigned int proglen,
>  				u32 pass, void *image)
>  {
> @@ -1450,6 +1467,20 @@ static inline void bpf_prog_kallsyms_del(struct bpf_prog *fp)
>  {
>  }
>  
> +static inline bool bpf_prog_need_blind(const struct bpf_prog *prog)
> +{
> +	return false;
> +}
> +
> +static inline
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog)
> +{
> +	return prog;
> +}
> +
> +static inline void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)
> +{
> +}
>  #endif /* CONFIG_BPF_JIT */
>  
>  void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index 1af5fb3f21d9..cc61fe57b98d 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -1506,7 +1506,10 @@ static void adjust_insn_arrays(struct bpf_prog *prog, u32 off, u32 len)
>  #endif
>  }
>  
> -struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
> +/* Now this function is used only to blind the main prog and must be invoked only when
> + * bpf_prog_need_blind() returns true.
> + */
> +struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct bpf_insn insn_buff[16], aux[2];
>  	struct bpf_prog *clone, *tmp;
> @@ -1514,13 +1517,17 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
>  	struct bpf_insn *insn;
>  	int i, rewritten;
>  
> -	if (!prog->blinding_requested || prog->blinded)
> -		return prog;
> +	if (env)
> +		prog = env->prog;
>  
>  	clone = bpf_prog_clone_create(prog, GFP_USER);
>  	if (!clone)
>  		return ERR_PTR(-ENOMEM);
>  
> +	/* make sure bpf_patch_insn_data() patches the correct prog */
> +	if (env)
> +		env->prog = clone;
> +
>  	insn_cnt = clone->len;
>  	insn = clone->insnsi;
>  
> @@ -1548,21 +1555,34 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
>  		if (!rewritten)
>  			continue;
>  
> -		tmp = bpf_patch_insn_single(clone, i, insn_buff, rewritten);
> -		if (IS_ERR(tmp)) {
> +		if (env)
> +			tmp = bpf_patch_insn_data(env, i, insn_buff, rewritten);
> +		else
> +			tmp = bpf_patch_insn_single(clone, i, insn_buff, rewritten);
> +
> +		if (IS_ERR_OR_NULL(tmp)) {
> +			if (env)
> +				/* restore the original prog */
> +				env->prog = prog;
>  			/* Patching may have repointed aux->prog during
>  			 * realloc from the original one, so we need to
>  			 * fix it up here on error.
>  			 */
>  			bpf_jit_prog_release_other(prog, clone);
> -			return tmp;
> +			return IS_ERR(tmp) ? tmp : ERR_PTR(-ENOMEM);
>  		}
>  
>  		clone = tmp;
>  		insn_delta = rewritten - 1;
>  
> -		/* Instructions arrays must be updated using absolute xlated offsets */
> -		adjust_insn_arrays(clone, prog->aux->subprog_start + i, rewritten);
> +		if (env)
> +			env->prog = clone;
> +		else
> +			/* Instructions arrays must be updated using absolute xlated offsets.
> +			 * The arrays have already been adjusted by bpf_patch_insn_data() when
> +			 * env is not NULL.
> +			 */
> +			adjust_insn_arrays(clone, i, rewritten);
>  
>  		/* Walk new program and skip insns we just inserted. */
>  		insn = clone->insnsi + i + insn_delta;
> @@ -2531,6 +2551,35 @@ static bool bpf_prog_select_interpreter(struct bpf_prog *fp)
>  	return select_interpreter;
>  }
>  
> +static struct bpf_prog *bpf_prog_jit_compile(struct bpf_prog *prog)
> +{
> +#ifdef CONFIG_BPF_JIT
> +	bool blinded = false;
> +	struct bpf_prog *orig_prog = prog;
> +
> +	if (bpf_prog_need_blind(orig_prog)) {
> +		prog = bpf_jit_blind_constants(NULL, orig_prog);
> +		/* If blinding was requested and we failed during blinding, we must fall
> +		 * back to the interpreter.
> +		 */
> +		if (IS_ERR(prog))
> +			return orig_prog;
> +		blinded = true;
> +	}
> +
> +	prog = bpf_int_jit_compile(prog);
> +	if (blinded) {
> +		if (!prog->jited) {
> +			bpf_jit_prog_release_other(orig_prog, prog);
> +			prog = orig_prog;
> +		} else {
> +			bpf_jit_prog_release_other(prog, orig_prog);
> +		}
> +	}
> +#endif
> +	return prog;
> +}
> +
>  /**
>   *	bpf_prog_select_runtime - select exec runtime for BPF program
>   *	@fp: bpf_prog populated with BPF program
> @@ -2570,7 +2619,7 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
>  		if (*err)
>  			return fp;
>  
> -		fp = bpf_int_jit_compile(fp);
> +		fp = bpf_prog_jit_compile(fp);
>  		bpf_prog_jit_attempt_done(fp);
>  		if (!fp->jited && jit_needed) {
>  			*err = -ENOTSUPP;
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index a431b7d50e1b..66cef3744fde 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -22215,8 +22215,8 @@ static void adjust_poke_descs(struct bpf_prog *prog, u32 off, u32 len)
>  	}
>  }
>  
> -static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> -					    const struct bpf_insn *patch, u32 len)
> +struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
> +				     const struct bpf_insn *patch, u32 len)
>  {
>  	struct bpf_prog *new_prog;
>  	struct bpf_insn_aux_data *new_data = NULL;
> @@ -22983,7 +22983,41 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
>  	return 0;
>  }
>  
> -static int jit_subprogs(struct bpf_verifier_env *env)
> +static u32 *dup_subprog_starts(struct bpf_verifier_env *env)
> +{
> +	u32 *starts = NULL;
> +
> +	starts = kvmalloc_objs(u32, env->subprog_cnt, GFP_KERNEL_ACCOUNT);
> +	if (!starts)
> +		return NULL;
> +	for (int i = 0; i < env->subprog_cnt; i++)
> +		starts[i] = env->subprog_info[i].start;
> +	return starts;
> +}
> +
> +static void restore_subprog_starts(struct bpf_verifier_env *env, u32 *orig_starts)
> +{
> +	for (int i = 0; i < env->subprog_cnt; i++)
> +		env->subprog_info[i].start = orig_starts[i];
> +}
> +
> +static struct bpf_insn_aux_data *dup_insn_aux_data(struct bpf_verifier_env *env)
> +{
> +	size_t size;
> +
> +	size = array_size(sizeof(struct bpf_insn_aux_data), env->prog->len);
> +	return kvmemdup(env->insn_aux_data, size, GFP_KERNEL_ACCOUNT);
> +}
> +
> +static void restore_insn_aux_data(struct bpf_verifier_env *env,
> +				  struct bpf_insn_aux_data *orig_insn_aux)
> +{
> +	/* the expanded elements are zero-filled, so no special handling is required */
> +	vfree(env->insn_aux_data);
> +	env->insn_aux_data = orig_insn_aux;
> +}
> +
> +static int __jit_subprogs(struct bpf_verifier_env *env)
>  {
>  	struct bpf_prog *prog = env->prog, **func, *tmp;
>  	int i, j, subprog_start, subprog_end = 0, len, subprog;
> @@ -22991,10 +23025,6 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  	struct bpf_insn *insn;
>  	void *old_bpf_func;
>  	int err, num_exentries;
> -	int old_len, subprog_start_adjustment = 0;
> -
> -	if (env->subprog_cnt <= 1)
> -		return 0;
>  
>  	for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
>  		if (!bpf_pseudo_func(insn) && !bpf_pseudo_call(insn))
> @@ -23063,10 +23093,11 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  			goto out_free;
>  		func[i]->is_func = 1;
>  		func[i]->sleepable = prog->sleepable;
> +		func[i]->blinded = prog->blinded;
>  		func[i]->aux->func_idx = i;
>  		/* Below members will be freed only at prog->aux */
>  		func[i]->aux->btf = prog->aux->btf;
> -		func[i]->aux->subprog_start = subprog_start + subprog_start_adjustment;
> +		func[i]->aux->subprog_start = subprog_start;
>  		func[i]->aux->func_info = prog->aux->func_info;
>  		func[i]->aux->func_info_cnt = prog->aux->func_info_cnt;
>  		func[i]->aux->poke_tab = prog->aux->poke_tab;
> @@ -23122,15 +23153,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  		func[i]->aux->might_sleep = env->subprog_info[i].might_sleep;
>  		if (!i)
>  			func[i]->aux->exception_boundary = env->seen_exception;
> -
> -		/*
> -		 * To properly pass the absolute subprog start to jit
> -		 * all instruction adjustments should be accumulated
> -		 */
> -		old_len = func[i]->len;
>  		func[i] = bpf_int_jit_compile(func[i]);
> -		subprog_start_adjustment += func[i]->len - old_len;
> -
>  		if (!func[i]->jited) {
>  			err = -ENOTSUPP;
>  			goto out_free;
> @@ -23256,16 +23279,83 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  	}
>  	kfree(func);
>  out_undo_insn:
> +	bpf_prog_jit_attempt_done(prog);
> +	return err;
> +}
> +
> +static int jit_subprogs(struct bpf_verifier_env *env)
> +{
> +	int err, i;
> +	bool blinded = false;
> +	struct bpf_insn *insn;
> +	struct bpf_prog *prog, *orig_prog;
> +	struct bpf_insn_aux_data *orig_insn_aux;
> +	u32 *orig_subprog_starts;
> +
> +	if (env->subprog_cnt <= 1)
> +		return 0;
> +
> +	prog = orig_prog = env->prog;
> +	if (bpf_prog_need_blind(orig_prog)) {
> +		orig_insn_aux = dup_insn_aux_data(env);
> +		if (!orig_insn_aux) {
> +			err = -ENOMEM;
> +			goto out_cleanup;
> +		}
> +		orig_subprog_starts = dup_subprog_starts(env);
> +		if (!orig_subprog_starts) {
> +			err = -ENOMEM;
> +			goto out_free_aux;
> +		}
> +		prog = bpf_jit_blind_constants(env, NULL);
> +		if (IS_ERR(prog)) {
> +			err = -ENOMEM;
> +			prog = orig_prog;
> +			goto out_restore;
> +		}
> +		blinded = true;
> +	}
> +
> +	err = __jit_subprogs(env);
> +	if (blinded) {
> +		if (err) {
> +			bpf_jit_prog_release_other(orig_prog, prog);
> +			/* roll back to the clean original prog */
> +			prog = env->prog = orig_prog;
> +			goto out_restore;
> +		} else {
> +			bpf_jit_prog_release_other(prog, orig_prog);
> +			kvfree(orig_subprog_starts);
> +			kvfree(orig_insn_aux);
> +		}
> +	} else if (err) {
> +		/* We will fall back to interpreter mode when err is not -EFAULT, before
> +		 * that, insn->off and insn->imm should be restored to their original values
> +		 * since they were modified by __jit_subprogs.
> +		 */
> +		if (err != -EFAULT) {
> +			for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
> +				if (!bpf_pseudo_call(insn))
> +					continue;
> +				insn->off = 0;
> +				insn->imm = env->insn_aux_data[i].call_imm;
> +			}
> +		}
> +		goto out_cleanup;
> +	}

Nit: The if/else branching and fallthroughs are not immediately clear
here. You could remove some of it if you did:

if (blinded) {
	if (err) {
		...
		goto out_restore;
	}

	bpf_jit_prog_release_other();
	...

	return 0;
}

/* Else !blinded */

if (!err)
	return 0;

/* Else err != 0*/

if (err == -EFAULT)

...
	

> +
> +	return 0;
> +
> +out_restore:
> +	restore_subprog_starts(env, orig_subprog_starts);
> +	restore_insn_aux_data(env, orig_insn_aux);
> +	kvfree(orig_subprog_starts);
> +out_free_aux:
> +	kvfree(orig_insn_aux);
> +out_cleanup:
>  	/* cleanup main prog to be interpreted */
>  	prog->jit_requested = 0;
>  	prog->blinding_requested = 0;
> -	for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
> -		if (!bpf_pseudo_call(insn))
> -			continue;
> -		insn->off = 0;
> -		insn->imm = env->insn_aux_data[i].call_imm;
> -	}
> -	bpf_prog_jit_attempt_done(prog);
>  	return err;
>  }
>  



^ permalink raw reply

* Re: (subset) [PATCH 05/15] dt-bindings: rtc: ingenic,rtc: Use generic power-controller schema
From: Alexandre Belloni @ 2026-04-03 16:09 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Rafael J. Wysocki,
	Ulf Hansson, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Saenz Julienne, Lee Jones, Liam Girdwood, Mark Brown,
	Shree Ramamoorthy, Jerome Neanne, Paul Cercueil, Dmitry Osipenko,
	Heiko Stuebner, Joseph Chen, Chris Zhong, Zhang Qing,
	Sebastian Reichel, Andreas Kemnade, Jonathan Neuschäfer,
	Lubomir Rintel, Julien Panis, Matti Vaittinen, Alexander Kurz,
	Krzysztof Kozlowski, André Draszik, Peng Fan (OSS)
  Cc: devicetree, linux-kernel, linux-rpi-kernel, linux-arm-kernel,
	linux-rtc, linux-rockchip, linux-samsung-soc, Peng Fan
In-Reply-To: <20260316-power-controller-v1-5-92c80e5e1744@nxp.com>

On Mon, 16 Mar 2026 22:47:40 +0800, Peng Fan (OSS) wrote:
> Convert the binding to use the generic power-controller schema instead by
> referencing power-controller.yaml and removing the local
> `system-power-controller` property definition.

Applied, thanks!

[05/15] dt-bindings: rtc: ingenic,rtc: Use generic power-controller schema
        https://git.kernel.org/abelloni/c/0452290110cc

Best regards,

-- 
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


^ permalink raw reply

* [PATCH v2 0/8] Add VIM4 MCU/FAN support
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau

The Khadas VIM4 board features a different MCU variant compared to
previous VIM boards.
While it shares the same I2C-based communication model,
it differs in some ways:

  - A distinct register map with its own volatile/writeable register set
  - A fan control with 0–100 levels instead of the 0–3 levels previously
  - A fan power supply gated through a regulator

This series adds support for this new variant by:

  1. Refactoring the khadas-mcu MFD driver to use per-variant data
     structures (regmap config, cells, fan platform data),
     and adding the khadas,vim4-mcu compatible string.

  2. Extending the fan thermal driver to retrieve the fan register
     and maximum level from platform_data,
     and to optionally manage a power regulator for the fan supply.

  3. Adding the corresponding DTS node for the VIM4, wiring the MCU to
     the I2C AO_A bus and exposing it as a thermal cooling device.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
Changes in v2:
- PATCH 5: Add regulator_disable on suspend thanks to Neil's feedback.
- Link to v1: https://lore.kernel.org/r/20260402-add-mcu-fan-khadas-vim4-v1-0-2b12eb4ac7b0@aliel.fr

---
Ronald Claveau (8):
      dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
      dt-bindings: i2c: amlogic: Add compatible for T7 SOC
      mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
      mfd: khadas-mcu: Add support for VIM4 MCU variant
      thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
      arm64: dts: amlogic: t7: Add i2c pinctrl node
      arm64: dts: amlogic: t7: Add i2c controller node
      arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node

 .../bindings/i2c/amlogic,meson6-i2c.yaml           |  13 ++-
 .../devicetree/bindings/mfd/khadas,mcu.yaml        |   5 +
 .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts  |  13 +++
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi        |  20 ++++
 drivers/mfd/khadas-mcu.c                           | 106 ++++++++++++++++++---
 drivers/thermal/khadas_mcu_fan.c                   |  49 ++++++++--
 include/linux/mfd/khadas-mcu.h                     |  39 +++++++-
 7 files changed, 222 insertions(+), 23 deletions(-)
---
base-commit: f7b64ed948718290209074a50bb0df17e5944873
change-id: 20260402-add-mcu-fan-khadas-vim4-ac1cbe553c9b
prerequisite-message-id: <20260326092645.1053261-1-jian.hu@amlogic.com>
prerequisite-patch-id: f03a086b4137158412b2d47b3de793b858de8dde
prerequisite-patch-id: 123970c9b29c2090440f2fd71c85d3c6fd8e36de
prerequisite-patch-id: 3e2e56b0926ba327b520f935df4ced5089bbe503
prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
prerequisite-change-id: 20260326-add-bcm43752-compatible-e264a4f7973a:v2
prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
prerequisite-change-id: 20260330-fix-invalid-property-bbe54d933f71:v2
prerequisite-patch-id: 8d675e7a239985c762843515b241f0a2f45f9c92
prerequisite-change-id: 20260331-fix-aml-t7-null-reset-2b608ebf9da4:v1
prerequisite-patch-id: 5b5de77af11747ce964404fb827d2ee2bff47ea5
prerequisite-patch-id: 1e37fc75fed1e533adee0f3e7e6ead1f8ff3c55c
prerequisite-patch-id: 65a5d76ffdbc9b3aab3385bb65cb027004c30e7e
prerequisite-patch-id: 2daf583fb5e7449a02bd217d8aca330171b598aa
prerequisite-patch-id: 237269801826dd3ad7fb16eb4d7d6d4eab504278
prerequisite-patch-id: d1ddf9b7710e91f8062de83bd7ba55afb2c4c112
prerequisite-patch-id: 57e9b08a968aedf543d3d0d56cf1ca4db20b2a16
prerequisite-patch-id: cd98b74fa56af72af2553f391c400981d83cd4f4
prerequisite-patch-id: b730f5e42be1d89d193e63a0265495cdbf2c7d7b
prerequisite-patch-id: 9debd88fa60febed9cd7208f86603b4c2d270520
prerequisite-patch-id: 314ef9ff0c4d1d15dab1dea9d92aa065f1eac3e9

Best regards,
-- 
Ronald Claveau <linux-kernel-dev@aliel.fr>



^ permalink raw reply

* [PATCH v2 5/8] thermal: khadas-mcu-fan: Add fan config from platform data Add regulator support
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Replace the hardcoded MAX_LEVEL constant and fan register
with values read from platform_data (fan_reg, max_level),
as new MCUs need different values.

Optionally acquire and enable a "fan" regulator supply
at probe time and on resume,
so boards that gate fan power through a regulator are handled.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 drivers/thermal/khadas_mcu_fan.c | 49 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 43 insertions(+), 6 deletions(-)

diff --git a/drivers/thermal/khadas_mcu_fan.c b/drivers/thermal/khadas_mcu_fan.c
index d35e5313bea41..24559bf65de46 100644
--- a/drivers/thermal/khadas_mcu_fan.c
+++ b/drivers/thermal/khadas_mcu_fan.c
@@ -13,13 +13,15 @@
 #include <linux/regmap.h>
 #include <linux/sysfs.h>
 #include <linux/thermal.h>
-
-#define MAX_LEVEL 3
+#include <linux/regulator/consumer.h>
 
 struct khadas_mcu_fan_ctx {
 	struct khadas_mcu *mcu;
+	unsigned int fan_reg;
 	unsigned int level;
+	unsigned int max_level;
 	struct thermal_cooling_device *cdev;
+	struct regulator *power;
 };
 
 static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
@@ -27,8 +29,7 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
 {
 	int ret;
 
-	ret = regmap_write(ctx->mcu->regmap, KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
-			   level);
+	ret = regmap_write(ctx->mcu->regmap, ctx->fan_reg, level);
 	if (ret)
 		return ret;
 
@@ -40,7 +41,9 @@ static int khadas_mcu_fan_set_level(struct khadas_mcu_fan_ctx *ctx,
 static int khadas_mcu_fan_get_max_state(struct thermal_cooling_device *cdev,
 					unsigned long *state)
 {
-	*state = MAX_LEVEL;
+	struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
+
+	*state = ctx->max_level;
 
 	return 0;
 }
@@ -61,7 +64,7 @@ khadas_mcu_fan_set_cur_state(struct thermal_cooling_device *cdev,
 {
 	struct khadas_mcu_fan_ctx *ctx = cdev->devdata;
 
-	if (state > MAX_LEVEL)
+	if (state > ctx->max_level)
 		return -EINVAL;
 
 	if (state == ctx->level)
@@ -83,11 +86,32 @@ static int khadas_mcu_fan_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct khadas_mcu_fan_ctx *ctx;
 	int ret;
+	const struct khadas_mcu_fan_pdata *pdata = dev_get_platdata(&pdev->dev);
 
 	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
 	if (!ctx)
 		return -ENOMEM;
+
 	ctx->mcu = mcu;
+	ctx->fan_reg   = pdata->fan_reg;
+	ctx->max_level = pdata->max_level;
+
+	ctx->power = devm_regulator_get_optional(dev->parent, "fan");
+	if (IS_ERR(ctx->power)) {
+		if (PTR_ERR(ctx->power) == -ENODEV)
+			ctx->power = NULL;
+		else
+			return PTR_ERR(ctx->power);
+	}
+
+	if (ctx->power) {
+		ret = regulator_enable(ctx->power);
+		if (ret) {
+			dev_err(dev, "Failed to enable fan power supply: %d\n", ret);
+			return ret;
+		}
+	}
+
 	platform_set_drvdata(pdev, ctx);
 
 	cdev = devm_thermal_of_cooling_device_register(dev->parent,
@@ -124,12 +148,25 @@ static int khadas_mcu_fan_suspend(struct device *dev)
 
 	ctx->level = level_save;
 
+	if (ctx->power) {
+		ret = regulator_disable(ctx->power);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
 static int khadas_mcu_fan_resume(struct device *dev)
 {
 	struct khadas_mcu_fan_ctx *ctx = dev_get_drvdata(dev);
+	int ret;
+
+	if (ctx->power) {
+		ret = regulator_enable(ctx->power);
+		if (ret)
+			return ret;
+	}
 
 	return khadas_mcu_fan_set_level(ctx, ctx->level);
 }

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 6/8] arm64: dts: amlogic: t7: Add i2c pinctrl node
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Add the T7 pinctrl used by the Khadas VIM4 for MCU communication.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index 7fe72c94ed623..e96fe10b251a0 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -376,6 +376,16 @@ mux {
 					};
 				};
 
+				i2c0_ao_d_pins: i2c0-ao-d {
+					mux {
+						groups = "i2c0_ao_sck_d",
+							 "i2c0_ao_sda_d";
+						function = "i2c0_ao";
+						bias-disable;
+						drive-strength-microamp = <3000>;
+					};
+				};
+
 				pwm_a_pins: pwm-a {
 					mux {
 						groups = "pwm_a";

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 1/8] dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

The Khadas VIM4 MCU register is slightly different
from previous boards' MCU.
This board also features a switchable power source for its fan.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
index 084960fd5a1fd..67769ef5d58b1 100644
--- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
+++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
@@ -18,6 +18,7 @@ properties:
   compatible:
     enum:
       - khadas,mcu # MCU revision is discoverable
+      - khadas,vim4-mcu
 
   "#cooling-cells": # Only needed for boards having FAN control feature
     const: 2
@@ -25,6 +26,10 @@ properties:
   reg:
     maxItems: 1
 
+  fan-supply:
+    description: Phandle to the regulator that powers the fan.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
 required:
   - compatible
   - reg

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 3/8] mfd: khadas-mcu: Add per-variant configuration infrastructure and VIM4 support
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Introduce a per-variant configuration structure (khadas_mcu_data)
holding the regmap config and MFD cells,
selected at probe time via the of_device_id match data.
This makes adding other variants straightforward.

Also introduce khadas_mcu_fan_pdata to pass fan register address and
maximum level to the fan sub-driver, removing the hardcoded constants.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 include/linux/mfd/khadas-mcu.h | 39 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/include/linux/mfd/khadas-mcu.h b/include/linux/mfd/khadas-mcu.h
index a99ba2ed0e4e0..75e275d3fa8d9 100644
--- a/include/linux/mfd/khadas-mcu.h
+++ b/include/linux/mfd/khadas-mcu.h
@@ -70,6 +70,13 @@
 #define KHADAS_MCU_WOL_INIT_START_REG		0x87 /* WO */
 #define KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG	0x88 /* WO */
 
+/* VIM4 specific registers */
+#define KHADAS_MCU_VIM4_REST_CONF_REG		0x2c /* WO - reset EEPROM */
+#define KHADAS_MCU_VIM4_LED_ON_RAM_REG		0x89 /* WO - LED volatile */
+#define KHADAS_MCU_VIM4_FAN_CTRL_REG		0x8a /* WO */
+#define KHADAS_MCU_VIM4_WDT_EN_REG		0x8b /* WO */
+#define KHADAS_MCU_VIM4_SYS_RST_REG		0x91 /* WO */
+
 enum {
 	KHADAS_BOARD_VIM1 = 0x1,
 	KHADAS_BOARD_VIM2,
@@ -82,10 +89,38 @@ enum {
  * struct khadas_mcu - Khadas MCU structure
  * @device:		device reference used for logs
  * @regmap:		register map
+ * @data:		pointer to variant-specific config
  */
 struct khadas_mcu {
-	struct device *dev;
-	struct regmap *regmap;
+	struct device			*dev;
+	struct regmap			*regmap;
+	const struct khadas_mcu_data	*data;
+};
+
+/**
+ * struct khadas_mcu_data - per-variant configuration
+ * @regmap_config:	regmap configuration
+ * @cells:		MFD sub-devices
+ * @ncells:		number of sub-devices
+ * @fan_cells:		MFD fan sub-devices
+ * @nfan_cells:		number of fan sub-devices
+ */
+struct khadas_mcu_data {
+	const struct regmap_config	*regmap_config;
+	const struct mfd_cell		*cells;
+	int				ncells;
+	const struct mfd_cell		*fan_cells;
+	int				nfan_cells;
+};
+
+/**
+ * struct khadas_mcu_fan_pdata - fan sub-driver configuration
+ * @fan_reg: register address to write the fan level
+ * @max_level: maximum fan level
+ */
+struct khadas_mcu_fan_pdata {
+	unsigned int fan_reg;
+	unsigned int max_level;
 };
 
 #endif /* MFD_KHADAS_MCU_H */

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 7/8] arm64: dts: amlogic: t7: Add i2c controller node
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Add the T7 i2c controller node used by the Khadas VIM4
for MCU communication.

Use amlogic,meson-axg-i2c as fallback compatible.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index e96fe10b251a0..560c9dce35266 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -711,6 +711,16 @@ pwm_ao_cd: pwm@60000 {
 				status = "disabled";
 			};
 
+			i2c_m_ao_a: i2c@76000 {
+				compatible = "amlogic,t7-i2c", "amlogic,meson-axg-i2c";
+				reg = <0x0 0x76000 0x0 0x48>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+				clocks = <&clkc_periphs CLKID_SYS_I2C_AO_A>;
+				status = "disabled";
+			};
+
 			sd_emmc_a: mmc@88000 {
 				compatible = "amlogic,t7-mmc", "amlogic,meson-axg-mmc";
 				reg = <0x0 0x88000 0x0 0x800>;

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 8/8] arm64: dts: amlogic: t7: khadas-vim4: Add i2c MCU fan node
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Enable and configure i2c MCU node to get fan working on Khadas VIM4.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 .../boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts      | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index 69d6118ba57e7..5d7f5390f3a66 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -157,6 +157,19 @@ wifi32k: wifi32k {
 	};
 };
 
+&i2c_m_ao_a {
+	status = "okay";
+	pinctrl-0 = <&i2c0_ao_d_pins>;
+	pinctrl-names = "default";
+
+	khadas_mcu: system-controller@18 {
+		compatible = "khadas,vim4-mcu";
+		reg = <0x18>;
+		fan-supply = <&vcc5v>;
+		#cooling-cells = <2>;
+	};
+};
+
 &pwm_ab {
 	status = "okay";
 	pinctrl-0 = <&pwm_a_pins>;

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 4/8] mfd: khadas-mcu: Add support for VIM4 MCU variant
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Refactor probe() to use per-variant khadas_mcu_data
instead of hardcoded globals.

Add dedicated regmap configuration and device data for the VIM4 MCU,
with its own volatile/writeable registers.

Add the fan control register
(0–100 levels vs 0–3 for previous supported boards).

Add a new compatible string "khadas,vim4-mcu".

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 drivers/mfd/khadas-mcu.c | 106 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 95 insertions(+), 11 deletions(-)

diff --git a/drivers/mfd/khadas-mcu.c b/drivers/mfd/khadas-mcu.c
index ba981a7886921..b36b3b3ab73c0 100644
--- a/drivers/mfd/khadas-mcu.c
+++ b/drivers/mfd/khadas-mcu.c
@@ -75,15 +75,91 @@ static const struct regmap_config khadas_mcu_regmap_config = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+static const struct khadas_mcu_fan_pdata khadas_mcu_fan_pdata = {
+	.fan_reg	= KHADAS_MCU_CMD_FAN_STATUS_CTRL_REG,
+	.max_level	= 3,
+};
+
 static struct mfd_cell khadas_mcu_fan_cells[] = {
 	/* VIM1/2 Rev13+ and VIM3 only */
-	{ .name = "khadas-mcu-fan-ctrl", },
+	{
+		.name = "khadas-mcu-fan-ctrl",
+		.platform_data = &khadas_mcu_fan_pdata,
+		.pdata_size    = sizeof(khadas_mcu_fan_pdata),
+	},
 };
 
 static struct mfd_cell khadas_mcu_cells[] = {
 	{ .name = "khadas-mcu-user-mem", },
 };
 
+static const struct khadas_mcu_data khadas_mcu_data = {
+	.regmap_config	= &khadas_mcu_regmap_config,
+	.cells		= khadas_mcu_cells,
+	.ncells		= ARRAY_SIZE(khadas_mcu_cells),
+	.fan_cells	= khadas_mcu_fan_cells,
+	.nfan_cells	= ARRAY_SIZE(khadas_mcu_fan_cells),
+};
+
+static bool khadas_mcu_vim4_reg_volatile(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case KHADAS_MCU_PWR_OFF_CMD_REG:
+	case KHADAS_MCU_VIM4_REST_CONF_REG:
+	case KHADAS_MCU_WOL_INIT_START_REG:
+	case KHADAS_MCU_VIM4_LED_ON_RAM_REG:
+	case KHADAS_MCU_VIM4_FAN_CTRL_REG:
+	case KHADAS_MCU_VIM4_WDT_EN_REG:
+	case KHADAS_MCU_VIM4_SYS_RST_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool khadas_mcu_vim4_reg_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case KHADAS_MCU_VERSION_0_REG:
+	case KHADAS_MCU_VERSION_1_REG:
+	case KHADAS_MCU_SHUTDOWN_NORMAL_STATUS_REG:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static const struct regmap_config khadas_mcu_vim4_regmap_config = {
+	.reg_bits	= 8,
+	.reg_stride	= 1,
+	.val_bits	= 8,
+	.max_register	= KHADAS_MCU_VIM4_SYS_RST_REG,
+	.volatile_reg	= khadas_mcu_vim4_reg_volatile,
+	.writeable_reg	= khadas_mcu_vim4_reg_writeable,
+	.cache_type	= REGCACHE_MAPLE,
+};
+
+static const struct khadas_mcu_fan_pdata khadas_vim4_fan_pdata = {
+	.fan_reg	= KHADAS_MCU_VIM4_FAN_CTRL_REG,
+	.max_level	= 0x64,
+};
+
+static const struct mfd_cell khadas_mcu_vim4_cells[] = {
+	{
+		.name		= "khadas-mcu-fan-ctrl",
+		.platform_data	= &khadas_vim4_fan_pdata,
+		.pdata_size	= sizeof(khadas_vim4_fan_pdata),
+	},
+};
+
+static const struct khadas_mcu_data khadas_vim4_mcu_data = {
+	.regmap_config	= &khadas_mcu_vim4_regmap_config,
+	.cells		= NULL,
+	.ncells		= 0,
+	.fan_cells	= khadas_mcu_vim4_cells,
+	.nfan_cells	= ARRAY_SIZE(khadas_mcu_vim4_cells),
+};
+
 static int khadas_mcu_probe(struct i2c_client *client)
 {
 	struct device *dev = &client->dev;
@@ -94,28 +170,35 @@ static int khadas_mcu_probe(struct i2c_client *client)
 	if (!ddata)
 		return -ENOMEM;
 
+	ddata->data = i2c_get_match_data(client);
+	if (!ddata->data)
+		return -EINVAL;
+
 	i2c_set_clientdata(client, ddata);
 
 	ddata->dev = dev;
 
-	ddata->regmap = devm_regmap_init_i2c(client, &khadas_mcu_regmap_config);
+	ddata->regmap = devm_regmap_init_i2c(client,
+					     ddata->data->regmap_config);
 	if (IS_ERR(ddata->regmap)) {
 		ret = PTR_ERR(ddata->regmap);
 		dev_err(dev, "Failed to allocate register map: %d\n", ret);
 		return ret;
 	}
 
-	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
-				   khadas_mcu_cells,
-				   ARRAY_SIZE(khadas_mcu_cells),
-				   NULL, 0, NULL);
-	if (ret)
-		return ret;
+	if (ddata->data->cells && ddata->data->ncells) {
+		ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
+					   ddata->data->cells,
+					   ddata->data->ncells,
+					   NULL, 0, NULL);
+		if (ret)
+			return ret;
+	}
 
 	if (of_property_present(dev->of_node, "#cooling-cells"))
 		return devm_mfd_add_devices(dev, PLATFORM_DEVID_NONE,
-					    khadas_mcu_fan_cells,
-					    ARRAY_SIZE(khadas_mcu_fan_cells),
+					    ddata->data->fan_cells,
+					    ddata->data->nfan_cells,
 					    NULL, 0, NULL);
 
 	return 0;
@@ -123,7 +206,8 @@ static int khadas_mcu_probe(struct i2c_client *client)
 
 #ifdef CONFIG_OF
 static const struct of_device_id khadas_mcu_of_match[] = {
-	{ .compatible = "khadas,mcu", },
+	{ .compatible = "khadas,mcu", .data = &khadas_mcu_data },
+	{ .compatible = "khadas,vim4-mcu", .data = &khadas_vim4_mcu_data },
 	{},
 };
 MODULE_DEVICE_TABLE(of, khadas_mcu_of_match);

-- 
2.49.0



^ permalink raw reply related

* [PATCH v2 2/8] dt-bindings: i2c: amlogic: Add compatible for T7 SOC
From: Ronald Claveau @ 2026-04-03 16:08 UTC (permalink / raw)
  To: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
	Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
	Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown
  Cc: linux-amlogic, devicetree, linux-kernel, linux-i2c,
	linux-arm-kernel, linux-pm, Ronald Claveau
In-Reply-To: <20260403-add-mcu-fan-khadas-vim4-v2-0-70536b22439a@aliel.fr>

Add the T7 SOC compatible which fallback to AXG compatible.

Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
---
 .../devicetree/bindings/i2c/amlogic,meson6-i2c.yaml         | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
index c4cc8af182807..7b59b60b62e5b 100644
--- a/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
+++ b/Documentation/devicetree/bindings/i2c/amlogic,meson6-i2c.yaml
@@ -16,10 +16,15 @@ allOf:
 
 properties:
   compatible:
-    enum:
-      - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
-      - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
-      - amlogic,meson-axg-i2c # AXG and compatible SoCs
+    oneOf:
+      - items:
+          - enum:
+              - amlogic,t7-i2c
+          - const: amlogic,meson-axg-i2c
+      - enum:
+          - amlogic,meson6-i2c # Meson6, Meson8 and compatible SoCs
+          - amlogic,meson-gxbb-i2c # GXBB and compatible SoCs
+          - amlogic,meson-axg-i2c # AXG and compatible SoCs
 
   reg:
     maxItems: 1

-- 
2.49.0



^ permalink raw reply related

* Re: [PATCH v10 00/12] barrier: Add smp_cond_load_{relaxed, acquire}_timeout()
From: Okanovic, Haris @ 2026-04-03 16:12 UTC (permalink / raw)
  To: ankur.a.arora@oracle.com
  Cc: joao.m.martins@oracle.com, xueshuai@linux.alibaba.com,
	david.laight.linux@gmail.com, boris.ostrovsky@oracle.com,
	memxor@gmail.com, zhenglifeng1@huawei.com, konrad.wilk@oracle.com,
	cl@gentwo.org, akpm@linux-foundation.org,
	linux-kernel@vger.kernel.org, catalin.marinas@arm.com,
	ast@kernel.org, rdunlap@infradead.org, daniel.lezcano@linaro.org,
	arnd@arndb.de, linux-arch@vger.kernel.org, will@kernel.org,
	mark.rutland@arm.com, peterz@infradead.org, bpf@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, Okanovic, Haris,
	rafael@kernel.org, linux-pm@vger.kernel.org
In-Reply-To: <20260316013651.3225328-1-ankur.a.arora@oracle.com>

Can we merge this series? I think there's an approval from every named
maintainer at this point.

Besides `perf sched` microbenchamrk that Ankur has been running, I've
observed 4-6% improvements in memcahed, cassandra, mysql, and
postgresql under certain loads. Other applications likely benefit too.

Thanks,
Haris Okanovic
AWS Graviton Software


On Sun, 2026-03-15 at 18:36 -0700, Ankur Arora wrote:
> CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you can confirm the sender and know the content is safe.
> 
> 
> 
> Hi,
> 
> This series adds waited variants of the smp_cond_load() primitives:
> smp_cond_load_relaxed_timeout(), and smp_cond_load_acquire_timeout().
> 
> With this version, the main remaining things are:
> 
>   - Review by PeterZ of the new interface tif_need_resched_relaxed_wait()
>     (patch 11, "sched: add need-resched timed wait interface").
> 
>   - Review of the BPF changes. This version simplifies the rqspinlock
>     changes by reusing the original error handling path
>     (patches 9, 10 "bpf/rqspinlock: switch check_timeout() to a clock
>     interface", "bpf/rqspinlock: Use smp_cond_load_acquire_timeout()").
> 
>   - Review of WFET handling. (patch 4, "arm64: support WFET in
>     smp_cond_load_relaxed_timeout()").
> 
> The new interfaces are meant for contexts where you want to wait on a
> condition variable for a finite duration. This is easy enough to do with
> a loop around cpu_relax(). There are, however, architectures (ex. arm64)
> that allow waiting on a cacheline instead.
> 
> So, these interfaces handle a mixture of spin/wait with a
> smp_cond_load() thrown in. The interfaces are:
> 
>    smp_cond_load_relaxed_timeout(ptr, cond_expr, time_expr, timeout)
>    smp_cond_load_acquire_timeout(ptr, cond_expr, time_expr, timeout)
> 
> The parameters, time_expr, timeout determine when to bail out.
> 
> Also add tif_need_resched_relaxed_wait() which wraps the pattern used
> in poll_idle() and abstracts out details of the interface and those
> of the scheduler.
> 
> In addition add atomic_cond_read_*_timeout(), atomic64_cond_read_*_timeout(),
> and atomic_long wrappers to the interfaces.
> 
> Finally update poll_idle() and resilient queued spinlocks to use them.
> 
> Changelog:
>   v9 [9]:
>    - s/@cond/@cond_expr/ (Randy Dunlap)
>    - Clarify that SMP_TIMEOUT_POLL_COUNT is only around memory
>      addresses. (David Laight)
>    - Add the missing config ARCH_HAS_CPU_RELAX in arch/arm64/Kconfig.
>      (Catalin Marinas).
>    - Switch to arch_counter_get_cntvct_stable() (via __delay_cycles())
>      in the cmpwait path instead of using arch_timer_read_counter().
>      (Catalin Marinas)
> 
>   v8 [0]:
>    - Defer evaluation of @time_expr_ns to when we hit the slowpath.
>       (comment from Alexei Starovoitov).
> 
>    - Mention that cpu_poll_relax() is better than raw CPU polling
>      only where ARCH_HAS_CPU_RELAX is defined.
>      - also define ARCH_HAS_CPU_RELAX for arm64.
>       (Came out of a discussion with Will Deacon.)
> 
>    - Split out WFET and WFE handling. I was doing both of these
>      in a common handler.
>      (From Will Deacon and in an earlier revision by Catalin Marinas.)
> 
>    - Add mentions of atomic_cond_read_{relaxed,acquire}(),
>      atomic_cond_read_{relaxed,acquire}_timeout() in
>      Documentation/atomic_t.txt.
> 
>    - Use the BIT() macro to do the checking in tif_bitset_relaxed_wait().
> 
>    - Cleanup unnecessary assignments, casts etc in poll_idle().
>      (From Rafael Wysocki.)
> 
>    - Fixup warnings from kernel build robot
> 
> 
>   v7 [1]:
>    - change the interface to separately provide the timeout. This is
>      useful for supporting WFET and similar primitives which can do
>      timed waiting (suggested by Arnd Bergmann).
> 
>    - Adapting rqspinlock code to this changed interface also
>      necessitated allowing time_expr to fail.
>    - rqspinlock changes to adapt to the new smp_cond_load_acquire_timeout().
> 
>    - add WFET support (suggested by Arnd Bergmann).
>    - add support for atomic-long wrappers.
>    - add a new scheduler interface tif_need_resched_relaxed_wait() which
>      encapsulates the polling logic used by poll_idle().
>      - interface suggested by (Rafael J. Wysocki).
> 
> 
>   v6 [2]:
>    - fixup missing timeout parameters in atomic64_cond_read_*_timeout()
>    - remove a race between setting of TIF_NEED_RESCHED and the call to
>      smp_cond_load_relaxed_timeout(). This would mean that dev->poll_time_limit
>      would be set even if we hadn't spent any time waiting.
>      (The original check compared against local_clock(), which would have been
>      fine, but I was instead using a cheaper check against _TIF_NEED_RESCHED.)
>    (Both from meta-CI bot)
> 
> 
>   v5 [3]:
>    - use cpu_poll_relax() instead of cpu_relax().
>    - instead of defining an arm64 specific
>      smp_cond_load_relaxed_timeout(), just define the appropriate
>      cpu_poll_relax().
>    - re-read the target pointer when we exit due to the time-check.
>    - s/SMP_TIMEOUT_SPIN_COUNT/SMP_TIMEOUT_POLL_COUNT/
>    (Suggested by Will Deacon)
> 
>    - add atomic_cond_read_*_timeout() and atomic64_cond_read_*_timeout()
>      interfaces.
>    - rqspinlock: use atomic_cond_read_acquire_timeout().
>    - cpuidle: use smp_cond_load_relaxed_tiemout() for polling.
>    (Suggested by Catalin Marinas)
> 
>    - rqspinlock: define SMP_TIMEOUT_POLL_COUNT to be 16k for non arm64
> 
> 
>   v4 [4]:
>     - naming change 's/timewait/timeout/'
>     - resilient spinlocks: get rid of res_smp_cond_load_acquire_waiting()
>       and fixup use of RES_CHECK_TIMEOUT().
>     (Both suggested by Catalin Marinas)
> 
>   v3 [5]:
>     - further interface simplifications (suggested by Catalin Marinas)
> 
>   v2 [6]:
>     - simplified the interface (suggested by Catalin Marinas)
>        - get rid of wait_policy, and a multitude of constants
>        - adds a slack parameter
>       This helped remove a fair amount of duplicated code duplication and in
>       hindsight unnecessary constants.
> 
>   v1 [7]:
>      - add wait_policy (coarse and fine)
>      - derive spin-count etc at runtime instead of using arbitrary
>        constants.
> 
> Haris Okanovic tested v4 of this series with poll_idle()/haltpoll patches. [8]
> 
> Comments appreciated!
> 
> Thanks
> Ankur
> 
>  [0] https://lore.kernel.org/lkml/20251215044919.460086-1-ankur.a.arora@oracle.com/
>  [1] https://lore.kernel.org/lkml/20251028053136.692462-1-ankur.a.arora@oracle.com/
>  [2] https://lore.kernel.org/lkml/20250911034655.3916002-1-ankur.a.arora@oracle.com/
>  [3] https://lore.kernel.org/lkml/20250911034655.3916002-1-ankur.a.arora@oracle.com/
>  [4] https://lore.kernel.org/lkml/20250829080735.3598416-1-ankur.a.arora@oracle.com/
>  [5] https://lore.kernel.org/lkml/20250627044805.945491-1-ankur.a.arora@oracle.com/
>  [6] https://lore.kernel.org/lkml/20250502085223.1316925-1-ankur.a.arora@oracle.com/
>  [7] https://lore.kernel.org/lkml/20250203214911.898276-1-ankur.a.arora@oracle.com/
>  [8] https://lore.kernel.org/lkml/2cecbf7fb23ee83a4ce027e1be3f46f97efd585c.camel@amazon.com/
>  [9] https://lore.kernel.org/lkml/20260209023153.2661784-1-ankur.a.arora@oracle.com/
> 
> Cc: Arnd Bergmann <arnd@arndb.de>
> Cc: Will Deacon <will@kernel.org>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: "Rafael J. Wysocki" <rafael@kernel.org>
> Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
> Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Cc: Alexei Starovoitov <ast@kernel.org>
> Cc: bpf@vger.kernel.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-pm@vger.kernel.org
> 
> Ankur Arora (12):
>   asm-generic: barrier: Add smp_cond_load_relaxed_timeout()
>   arm64: barrier: Support smp_cond_load_relaxed_timeout()
>   arm64/delay: move some constants out to a separate header
>   arm64: support WFET in smp_cond_load_relaxed_timeout()
>   arm64: rqspinlock: Remove private copy of
>     smp_cond_load_acquire_timewait()
>   asm-generic: barrier: Add smp_cond_load_acquire_timeout()
>   atomic: Add atomic_cond_read_*_timeout()
>   locking/atomic: scripts: build atomic_long_cond_read_*_timeout()
>   bpf/rqspinlock: switch check_timeout() to a clock interface
>   bpf/rqspinlock: Use smp_cond_load_acquire_timeout()
>   sched: add need-resched timed wait interface
>   cpuidle/poll_state: Wait for need-resched via
>     tif_need_resched_relaxed_wait()
> 
>  Documentation/atomic_t.txt           | 14 +++--
>  arch/arm64/Kconfig                   |  3 +
>  arch/arm64/include/asm/barrier.h     | 23 +++++++
>  arch/arm64/include/asm/cmpxchg.h     | 62 +++++++++++++++----
>  arch/arm64/include/asm/delay-const.h | 27 +++++++++
>  arch/arm64/include/asm/rqspinlock.h  | 85 --------------------------
>  arch/arm64/lib/delay.c               | 15 ++---
>  drivers/cpuidle/poll_state.c         | 21 +------
>  drivers/soc/qcom/rpmh-rsc.c          |  8 +--
>  include/asm-generic/barrier.h        | 90 ++++++++++++++++++++++++++++
>  include/linux/atomic.h               | 10 ++++
>  include/linux/atomic/atomic-long.h   | 18 +++---
>  include/linux/sched/idle.h           | 29 +++++++++
>  kernel/bpf/rqspinlock.c              | 77 +++++++++++++++---------
>  scripts/atomic/gen-atomic-long.sh    | 16 +++--
>  15 files changed, 320 insertions(+), 178 deletions(-)
>  create mode 100644 arch/arm64/include/asm/delay-const.h
> 
> --
> 2.31.1
> 

-- 
Regards,
Haris Okanovic
AWS Graviton Software


^ permalink raw reply

* Re: [PATCH v3 1/2] mailbox: Use per-thread completion to fix wrong completion order
From: Jassi Brar @ 2026-04-03 16:19 UTC (permalink / raw)
  To: Joonwon Kang
  Cc: angelogioacchino.delregno, jonathanh, linux-arm-kernel,
	linux-kernel, linux-mediatek, linux-tegra, matthias.bgg, stable,
	thierry.reding
In-Reply-To: <20260403145119.2581034-1-joonwonkang@google.com>

On Fri, Apr 3, 2026 at 9:51 AM Joonwon Kang <joonwonkang@google.com> wrote:
>
> > On Thu, Apr 2, 2026 at 12:07 PM Joonwon Kang <joonwonkang@google.com> wrote:
> > >
> > > Previously, a sender thread in mbox_send_message() could be woken up at
> > > a wrong time in blocking mode. It is because there was only a single
> > > completion for a channel whereas messages from multiple threads could be
> > > sent in any order; since the shared completion could be signalled in any
> > > order, it could wake up a wrong sender thread.
> > >
> > > This commit resolves the false wake-up issue with the following changes:
> > > - Completions are created just as many as the number of concurrent sender
> > >   threads
> > > - A completion is created on a sender thread's stack
> > > - Each slot of the message queue, i.e. `msg_data`, contains a pointer to
> > >   its target completion
> > > - tx_tick() signals the completion of the currently active slot of the
> > >   message queue
> > >
> > I think I reviewed it already or is this happening on
> > one-channel-one-client usage? Because mailbox api does not support
> > channels shared among multiple clients.
>
> Yes, this patch is handling the one-channel-one-client usage but when that
> single channel is shared between multiple threads.

hmm.... how is this not single-channel-multiple-clients ?
A channel is returned as an opaque token to the clients, if that
client shares that with other threads - they will race.
It is the job of the original client to serialize its threads' access
to the channel.

> From my understanding, the
> discussion back then ended with how to circumvent the issue rather than whether
> we will eventually solve this in the mailbox framework or not, and if yes, how
> we will, and if not, why.

It will be interesting to see how many current clients actually need
to share channels. If there are enough, it makes sense to implement
some helper api
on top of existing code, instead of changing its nature totally.

Thanks
Jassi


^ permalink raw reply

* Re: [PATCH V10 03/13] PCI: dwc: Parse Root Port nodes in dw_pcie_host_init()
From: Manivannan Sadhasivam @ 2026-04-03 16:20 UTC (permalink / raw)
  To: Sherry Sun
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
	lpieralisi, kwilczynski, bhelgaas, hongxing.zhu, l.stach, imx,
	linux-pci, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260402095107.205439-4-sherry.sun@nxp.com>

On Thu, Apr 02, 2026 at 05:50:57PM +0800, Sherry Sun wrote:
> Add support for parsing Root Port child nodes in dw_pcie_host_init()
> using pci_host_common_parse_ports(). This allows DWC-based drivers to
> specify Root Port properties (like reset GPIOs) in individual Root Port
> nodes rather than in the host bridge node.
> 
> Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> ---
>  drivers/pci/controller/dwc/pcie-designware-host.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
> index da152c31bb2e..f6fca984fb34 100644
> --- a/drivers/pci/controller/dwc/pcie-designware-host.c
> +++ b/drivers/pci/controller/dwc/pcie-designware-host.c
> @@ -20,6 +20,7 @@
>  #include <linux/platform_device.h>
>  
>  #include "../../pci.h"
> +#include "../pci-host-common.h"
>  #include "pcie-designware.h"
>  
>  static struct pci_ops dw_pcie_ops;
> @@ -581,6 +582,13 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
>  
>  	pp->bridge = bridge;
>  
> +	/* Parse Root Port nodes if present */
> +	ret = pci_host_common_parse_ports(dev, bridge);
> +	if (ret && ret != -ENOENT) {
> +		dev_err(dev, "Failed to parse Root Port nodes: %d\n", ret);
> +		return ret;

Won't this change break drivers that parse Root Ports on their own? Either you
need to modify them also in this change or call this API from imx6 driver and
let other drivers switch to it in a phased manner.

I perfer the latter.

- Mani

-- 
மணிவண்ணன் சதாசிவம்


^ permalink raw reply

* Re: [PATCH V10 04/13] PCI: imx6: Assert PERST# before enabling regulators
From: Manivannan Sadhasivam @ 2026-04-03 16:29 UTC (permalink / raw)
  To: Sherry Sun
  Cc: robh, krzk+dt, conor+dt, Frank.Li, s.hauer, kernel, festevam,
	lpieralisi, kwilczynski, bhelgaas, hongxing.zhu, l.stach, imx,
	linux-pci, linux-arm-kernel, devicetree, linux-kernel
In-Reply-To: <20260402095107.205439-5-sherry.sun@nxp.com>

On Thu, Apr 02, 2026 at 05:50:58PM +0800, Sherry Sun wrote:
> According to the PCIe initialization requirements, PERST# signal should
> be asserted before applying power to the PCIe device, and deasserted
> after power and reference clock are stable.
> 

Spec wording is not quite like this. Spec mandates asserting PERST# *before*
stopping refclk and powering down the device and deasserting it *after* applying
power and refclk stable.

I believe you want to assert PERST# before enabling regulator to prevent the
endpoint from functioning? If so, is it due to refclk not available yet or some
other reason?

> Currently, the driver enables the vpcie3v3aux regulator in
> imx_pcie_probe() before PERST# is asserted in imx_pcie_host_init(),
> which violates the PCIe power sequencing requirements. However, there
> is no issue so far because PERST# is requested as GPIOD_OUT_HIGH in
> imx_pcie_probe(), which guarantees that PERST# is asserted before
> enabling the vpcie3v3aux regulator.
> 
> This is prepare for the upcoming changes that will parse the reset
> property using the new Root Port binding, which will use GPIOD_ASIS
> when requesting the reset GPIO. With GPIOD_ASIS, the GPIO state is not
> guaranteed, so explicit sequencing is required.
> 
> Fix the power sequencing by:
> 1. Moving vpcie3v3aux regulator enable from probe to
>    imx_pcie_host_init(), where it can be properly sequenced with PERST#.
> 2. Moving imx_pcie_assert_perst() before regulator and clock enable to
>    ensure correct ordering.
> 
> The vpcie3v3aux regulator is kept enabled for the entire PCIe controller
> lifecycle and automatically disabled on device removal via devm cleanup.
> 

vpcie3v3aux handling should be in a separate patch.

- Mani

> Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
> ---
>  drivers/pci/controller/dwc/pci-imx6.c | 49 +++++++++++++++++++++------
>  1 file changed, 39 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 45d70ae7e04f..948ffb75d122 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -166,6 +166,8 @@ struct imx_pcie {
>  	u32			tx_swing_full;
>  	u32			tx_swing_low;
>  	struct regulator	*vpcie;
> +	struct regulator	*vpcie_aux;
> +	bool			vpcie_aux_enabled;
>  	struct regulator	*vph;
>  	void __iomem		*phy_base;
>  
> @@ -1220,6 +1222,13 @@ static void imx_pcie_disable_device(struct pci_host_bridge *bridge,
>  	imx_pcie_remove_lut(imx_pcie, pci_dev_id(pdev));
>  }
>  
> +static void imx_pcie_vpcie_aux_disable(void *data)
> +{
> +	struct regulator *vpcie_aux = data;
> +
> +	regulator_disable(vpcie_aux);
> +}
> +
>  static void imx_pcie_assert_perst(struct imx_pcie *imx_pcie, bool assert)
>  {
>  	if (assert) {
> @@ -1240,6 +1249,24 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>  	struct imx_pcie *imx_pcie = to_imx_pcie(pci);
>  	int ret;
>  
> +	imx_pcie_assert_perst(imx_pcie, true);
> +
> +	/* Keep 3.3Vaux supply enabled for the entire PCIe controller lifecycle */
> +	if (imx_pcie->vpcie_aux && !imx_pcie->vpcie_aux_enabled) {
> +		ret = regulator_enable(imx_pcie->vpcie_aux);
> +		if (ret) {
> +			dev_err(dev, "failed to enable vpcie_aux regulator: %d\n",
> +				ret);
> +			return ret;
> +		}
> +		imx_pcie->vpcie_aux_enabled = true;
> +
> +		ret = devm_add_action_or_reset(dev, imx_pcie_vpcie_aux_disable,
> +					       imx_pcie->vpcie_aux);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	if (imx_pcie->vpcie) {
>  		ret = regulator_enable(imx_pcie->vpcie);
>  		if (ret) {
> @@ -1249,25 +1276,24 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
>  		}
>  	}
>  
> +	ret = imx_pcie_clk_enable(imx_pcie);
> +	if (ret) {
> +		dev_err(dev, "unable to enable pcie clocks: %d\n", ret);
> +		goto err_reg_disable;
> +	}
> +
>  	if (pp->bridge && imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT)) {
>  		pp->bridge->enable_device = imx_pcie_enable_device;
>  		pp->bridge->disable_device = imx_pcie_disable_device;
>  	}
>  
>  	imx_pcie_assert_core_reset(imx_pcie);
> -	imx_pcie_assert_perst(imx_pcie, true);
>  
>  	if (imx_pcie->drvdata->init_phy)
>  		imx_pcie->drvdata->init_phy(imx_pcie);
>  
>  	imx_pcie_configure_type(imx_pcie);
>  
> -	ret = imx_pcie_clk_enable(imx_pcie);
> -	if (ret) {
> -		dev_err(dev, "unable to enable pcie clocks: %d\n", ret);
> -		goto err_reg_disable;
> -	}
> -
>  	if (imx_pcie->phy) {
>  		ret = phy_init(imx_pcie->phy);
>  		if (ret) {
> @@ -1780,9 +1806,12 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  	of_property_read_u32(node, "fsl,max-link-speed", &pci->max_link_speed);
>  	imx_pcie->supports_clkreq = of_property_read_bool(node, "supports-clkreq");
>  
> -	ret = devm_regulator_get_enable_optional(&pdev->dev, "vpcie3v3aux");
> -	if (ret < 0 && ret != -ENODEV)
> -		return dev_err_probe(dev, ret, "failed to enable Vaux supply\n");
> +	imx_pcie->vpcie_aux = devm_regulator_get_optional(&pdev->dev, "vpcie3v3aux");
> +	if (IS_ERR(imx_pcie->vpcie_aux)) {
> +		if (PTR_ERR(imx_pcie->vpcie_aux) != -ENODEV)
> +			return PTR_ERR(imx_pcie->vpcie_aux);
> +		imx_pcie->vpcie_aux = NULL;
> +	}
>  
>  	imx_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie");
>  	if (IS_ERR(imx_pcie->vpcie)) {
> -- 
> 2.37.1
> 

-- 
மணிவண்ணன் சதாசிவம்


^ permalink raw reply

* Re: [PATCH 1/2] crypto: atmel-ecc - add Thorsten Blum as maintainer
From: Nicolas Ferre @ 2026-04-03 16:29 UTC (permalink / raw)
  To: Thorsten Blum, Herbert Xu, David S. Miller, Alexandre Belloni,
	Claudiu Beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260403112135.903162-5-thorsten.blum@linux.dev>

On 03/04/2026 at 13:21, Thorsten Blum wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Add Thorsten Blum as maintainer of the atmel-ecc driver.
> 
> Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>

Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>

> ---
>   MAINTAINERS | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c3fe46d7c4bc..c23110384b91 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17216,9 +17216,10 @@ F:     Documentation/devicetree/bindings/media/microchip,csi2dc.yaml
>   F:     drivers/media/platform/microchip/microchip-csi2dc.c
> 
>   MICROCHIP ECC DRIVER
> +M:     Thorsten Blum <thorsten.blum@linux.dev>
>   L:     linux-crypto@vger.kernel.org
> -S:     Orphan
> -F:     drivers/crypto/atmel-ecc.*
> +S:     Maintained
> +F:     drivers/crypto/atmel-ecc.c
> 
>   MICROCHIP EIC DRIVER
>   M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>



^ permalink raw reply

* Re: [PATCH 2/2] crypto: atmel-sha204a - add Thorsten Blum as maintainer
From: Nicolas Ferre @ 2026-04-03 16:30 UTC (permalink / raw)
  To: Thorsten Blum, Herbert Xu, David S. Miller, Alexandre Belloni,
	Claudiu Beznea
  Cc: linux-crypto, linux-arm-kernel, linux-kernel
In-Reply-To: <20260403112135.903162-7-thorsten.blum@linux.dev>

On 03/04/2026 at 13:21, Thorsten Blum wrote:
> Add a MAINTAINERS entry for the atmel-sha204a driver and Thorsten Blum
> as maintainer.
> 
> Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>

Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>

Thanks Thorsten for taking care of those components.

Best regards,
   Nicolas

> ---
>   MAINTAINERS | 6 ++++++
>   1 file changed, 6 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c23110384b91..7317d80592cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -17197,6 +17197,12 @@ S:     Supported
>   F:     Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
>   F:     drivers/spi/spi-at91-usart.c
> 
> +MICROCHIP ATSHA204A DRIVER
> +M:     Thorsten Blum <thorsten.blum@linux.dev>
> +L:     linux-crypto@vger.kernel.org
> +S:     Maintained
> +F:     drivers/crypto/atmel-sha204a.c
> +
>   MICROCHIP AUDIO ASOC DRIVERS
>   M:     Claudiu Beznea <claudiu.beznea@tuxon.dev>
>   M:     Andrei Simion <andrei.simion@microchip.com>



^ permalink raw reply

* Re: [PATCH v3 2/2] mailbox: Make mbox_send_message() return error code when tx fails
From: Jassi Brar @ 2026-04-03 16:36 UTC (permalink / raw)
  To: Joonwon Kang
  Cc: angelogioacchino.delregno, jonathanh, linux-arm-kernel,
	linux-kernel, linux-mediatek, linux-tegra, matthias.bgg, stable,
	thierry.reding, akpm
In-Reply-To: <20260403151950.2592581-1-joonwonkang@google.com>

On Fri, Apr 3, 2026 at 10:19 AM Joonwon Kang <joonwonkang@google.com> wrote:
>
> > On Thu, Apr 2, 2026 at 12:07 PM Joonwon Kang <joonwonkang@google.com> wrote:
> > >
> > > When the mailbox controller failed transmitting message, the error code
> > > was only passed to the client's tx done handler and not to
> > > mbox_send_message(). For this reason, the function could return a false
> > > success. This commit resolves the issue by introducing the tx status and
> > > checking it before mbox_send_message() returns.
> > >
> > Can you please share the scenario when this becomes necessary? This
> > can potentially change the ground underneath some clients, so we have
> > to be sure this is really useful.
>
> I would say the problem here is generic enough to apply to all the cases where
> the send result needs to be checked. Since the return value of the send API is
> not the real send result, any users who believe that this blocking send API
> will return the real send result could fall for that. For example, users may
> think the send was successful even though it was not actually. I believe it is
> uncommon that users have to register a callback solely to get the send result
> even though they are using the blocking send API already. Also, I guess there
> is no special reason why only the mailbox send API should work this way among
> other typical blocking send APIs. For these reasons, this patch makes the send
> API return the real send result. This way, users will not need to register the
> redundant callback and I think the return value will align with their common
> expectation.
>
Clients submit a message into the Mailbox subsystem to be sent out to
the remote side which can happen immediately or later.
If submission fails, clients get immediately notified. If transmission
fails (which is now internal to the subsystem) it is reported to the
client by a callback.
If the API was called mbox_submit_message (which it actually is)
instead of mbox_send_message, there would be no confusion.
We can argue how good/bad the current implementation is, but the fact
is that it is here. And I am reluctant to cause churn without good
reason.
Again, as I said, any, _legal_, setup scenario will help me come over
my reluctance.

Thanks
Jassi


^ permalink raw reply

* Re: [PATCH bpf-next v12 2/5] bpf: Pass bpf_verifier_env to JIT
From: Emil Tsalapatis @ 2026-04-03 16:38 UTC (permalink / raw)
  To: Xu Kuohai, bpf, linux-kernel, linux-arm-kernel
  Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
	Martin KaFai Lau, Eduard Zingerman, Yonghong Song, Puranjay Mohan,
	Anton Protopopov, Alexis Lothoré, Shahab Vahedi,
	Russell King, Tiezhu Yang, Hengqi Chen, Johan Almbladh,
	Paul Burton, Hari Bathini, Christophe Leroy, Naveen N Rao,
	Luke Nelson, Xi Wang, Björn Töpel, Pu Lehui,
	Ilya Leoshkevich, Heiko Carstens, Vasily Gorbik, David S . Miller,
	Wang YanQing
In-Reply-To: <20260403132811.753894-3-xukuohai@huaweicloud.com>

On Fri Apr 3, 2026 at 9:28 AM EDT, Xu Kuohai wrote:
> From: Xu Kuohai <xukuohai@huawei.com>
>
> Pass bpf_verifier_env to bpf_int_jit_compile(). The follow-up patch will
> use env->insn_aux_data in the JIT stage to detect indirect jump targets.
>
> Since bpf_prog_select_runtime() can be called by cbpf and lib/test_bpf.c
> code without verifier, introduce helper __bpf_prog_select_runtime()
> to accept the env parameter.
>
> Remove the call to bpf_prog_select_runtime() in bpf_prog_load(), and
> switch to call __bpf_prog_select_runtime() in the verifier, with env
> variable passed. The original bpf_prog_select_runtime() is preserved for
> cbpf and lib/test_bpf.c, where env is NULL.
>
> Now all constants blinding calls are moved into the verifier, except
> the cbpf and lib/test_bpf.c cases. The instructions arrays are adjusted
> by bpf_patch_insn_data() function for normal cases, so there is no need
> to call adjust_insn_arrays() in bpf_jit_blind_constants(). Remove it.
>

Provided the bot comments are fixed (also check the comment Sashiko raises about a
kvmalloc()-to-vfree mismatch):

Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>

> Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com>
> Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
> ---
>  arch/arc/net/bpf_jit_core.c      |  2 +-
>  arch/arm/net/bpf_jit_32.c        |  2 +-
>  arch/arm64/net/bpf_jit_comp.c    |  2 +-
>  arch/loongarch/net/bpf_jit.c     |  2 +-
>  arch/mips/net/bpf_jit_comp.c     |  2 +-
>  arch/parisc/net/bpf_jit_core.c   |  2 +-
>  arch/powerpc/net/bpf_jit_comp.c  |  2 +-
>  arch/riscv/net/bpf_jit_core.c    |  2 +-
>  arch/s390/net/bpf_jit_comp.c     |  2 +-
>  arch/sparc/net/bpf_jit_comp_64.c |  2 +-
>  arch/x86/net/bpf_jit_comp.c      |  2 +-
>  arch/x86/net/bpf_jit_comp32.c    |  2 +-
>  include/linux/filter.h           | 17 +++++-
>  kernel/bpf/core.c                | 93 +++++++++++++++++---------------
>  kernel/bpf/syscall.c             |  4 --
>  kernel/bpf/verifier.c            | 36 +++++++------
>  16 files changed, 98 insertions(+), 76 deletions(-)
>
> diff --git a/arch/arc/net/bpf_jit_core.c b/arch/arc/net/bpf_jit_core.c
> index 973ceae48675..639a2736f029 100644
> --- a/arch/arc/net/bpf_jit_core.c
> +++ b/arch/arc/net/bpf_jit_core.c
> @@ -1400,7 +1400,7 @@ static struct bpf_prog *do_extra_pass(struct bpf_prog *prog)
>   * (re)locations involved that their addresses are not known
>   * during the first run.
>   */
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	vm_dump(prog);
>  
> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
> index e6b1bb2de627..1628b6fc70a4 100644
> --- a/arch/arm/net/bpf_jit_32.c
> +++ b/arch/arm/net/bpf_jit_32.c
> @@ -2142,7 +2142,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *header;
>  	struct jit_ctx ctx;
> diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
> index cd5a72fff500..7212ec89dfe3 100644
> --- a/arch/arm64/net/bpf_jit_comp.c
> +++ b/arch/arm64/net/bpf_jit_comp.c
> @@ -2006,7 +2006,7 @@ struct arm64_jit_data {
>  	struct jit_ctx ctx;
>  };
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	int image_size, prog_size, extable_size, extable_align, extable_offset;
>  	struct bpf_binary_header *header;
> diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
> index fcc8c0c29fb0..5149ce4cef7e 100644
> --- a/arch/loongarch/net/bpf_jit.c
> +++ b/arch/loongarch/net/bpf_jit.c
> @@ -1920,7 +1920,7 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
>  	return ret < 0 ? ret : ret * LOONGARCH_INSN_SIZE;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	bool extra_pass = false;
>  	u8 *image_ptr, *ro_image_ptr;
> diff --git a/arch/mips/net/bpf_jit_comp.c b/arch/mips/net/bpf_jit_comp.c
> index d2b6c955f18e..6ee4abe6a1f7 100644
> --- a/arch/mips/net/bpf_jit_comp.c
> +++ b/arch/mips/net/bpf_jit_comp.c
> @@ -909,7 +909,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *header = NULL;
>  	struct jit_context ctx;
> diff --git a/arch/parisc/net/bpf_jit_core.c b/arch/parisc/net/bpf_jit_core.c
> index 35dca372b5df..172770132440 100644
> --- a/arch/parisc/net/bpf_jit_core.c
> +++ b/arch/parisc/net/bpf_jit_core.c
> @@ -41,7 +41,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	unsigned int prog_size = 0, extable_size = 0;
>  	bool extra_pass = false;
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 711028bebea3..27fecb4cc063 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -129,7 +129,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *fp)
>  {
>  	u32 proglen;
>  	u32 alloclen;
> diff --git a/arch/riscv/net/bpf_jit_core.c b/arch/riscv/net/bpf_jit_core.c
> index 527baa50dc68..768ac686b359 100644
> --- a/arch/riscv/net/bpf_jit_core.c
> +++ b/arch/riscv/net/bpf_jit_core.c
> @@ -41,7 +41,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	unsigned int prog_size = 0, extable_size = 0;
>  	bool extra_pass = false;
> diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
> index 2dfc279b1be2..94128fe6be23 100644
> --- a/arch/s390/net/bpf_jit_comp.c
> +++ b/arch/s390/net/bpf_jit_comp.c
> @@ -2312,7 +2312,7 @@ static struct bpf_binary_header *bpf_jit_alloc(struct bpf_jit *jit,
>  /*
>   * Compile eBPF program "fp"
>   */
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *fp)
>  {
>  	struct bpf_binary_header *header;
>  	struct s390_jit_data *jit_data;
> diff --git a/arch/sparc/net/bpf_jit_comp_64.c b/arch/sparc/net/bpf_jit_comp_64.c
> index e83e29137566..2fa0e9375127 100644
> --- a/arch/sparc/net/bpf_jit_comp_64.c
> +++ b/arch/sparc/net/bpf_jit_comp_64.c
> @@ -1477,7 +1477,7 @@ struct sparc64_jit_data {
>  	struct jit_ctx ctx;
>  };
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct sparc64_jit_data *jit_data;
>  	struct bpf_binary_header *header;
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index 77d00a8dec87..72d9a5faa230 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -3713,7 +3713,7 @@ struct x64_jit_data {
>  #define MAX_PASSES 20
>  #define PADDING_PASSES (MAX_PASSES - 5)
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *rw_header = NULL;
>  	struct bpf_binary_header *header = NULL;
> diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
> index 5f259577614a..852baf2e4db4 100644
> --- a/arch/x86/net/bpf_jit_comp32.c
> +++ b/arch/x86/net/bpf_jit_comp32.c
> @@ -2518,7 +2518,7 @@ bool bpf_jit_needs_zext(void)
>  	return true;
>  }
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	struct bpf_binary_header *header = NULL;
>  	int proglen, oldproglen = 0;
> diff --git a/include/linux/filter.h b/include/linux/filter.h
> index d396e55c9a1d..83f37d38c5c1 100644
> --- a/include/linux/filter.h
> +++ b/include/linux/filter.h
> @@ -1107,6 +1107,8 @@ static inline int sk_filter_reason(struct sock *sk, struct sk_buff *skb,
>  	return sk_filter_trim_cap(sk, skb, 1, reason);
>  }
>  
> +struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct bpf_prog *fp,
> +					   int *err);
>  struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err);
>  void bpf_prog_free(struct bpf_prog *fp);
>  
> @@ -1152,7 +1154,7 @@ u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5);
>  	((u64 (*)(u64, u64, u64, u64, u64, const struct bpf_insn *)) \
>  	 (void *)__bpf_call_base)
>  
> -struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog);
> +struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog);
>  void bpf_jit_compile(struct bpf_prog *prog);
>  bool bpf_jit_needs_zext(void);
>  bool bpf_jit_inlines_helper_call(s32 imm);
> @@ -1187,12 +1189,25 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
>  #ifdef CONFIG_BPF_SYSCALL
>  struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
>  				     const struct bpf_insn *patch, u32 len);
> +struct bpf_insn_aux_data *bpf_dup_insn_aux_data(struct bpf_verifier_env *env);
> +void bpf_restore_insn_aux_data(struct bpf_verifier_env *env,
> +			       struct bpf_insn_aux_data *orig_insn_aux);
>  #else
>  static inline struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 off,
>  						   const struct bpf_insn *patch, u32 len)
>  {
>  	return ERR_PTR(-ENOTSUPP);
>  }
> +
> +static inline struct bpf_insn_aux_data *bpf_dup_insn_aux_data(struct bpf_verifier_env *env)
> +{
> +	return NULL;
> +}
> +
> +static inline void bpf_restore_insn_aux_data(struct bpf_verifier_env *env,
> +					     struct bpf_insn_aux_data *orig_insn_aux)
> +{
> +}
>  #endif /* CONFIG_BPF_SYSCALL */
>  
>  int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt);
> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> index cc61fe57b98d..093ab0f68c81 100644
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c
> @@ -1489,23 +1489,6 @@ void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other)
>  	bpf_prog_clone_free(fp_other);
>  }
>  
> -static void adjust_insn_arrays(struct bpf_prog *prog, u32 off, u32 len)
> -{
> -#ifdef CONFIG_BPF_SYSCALL
> -	struct bpf_map *map;
> -	int i;
> -
> -	if (len <= 1)
> -		return;
> -
> -	for (i = 0; i < prog->aux->used_map_cnt; i++) {
> -		map = prog->aux->used_maps[i];
> -		if (map->map_type == BPF_MAP_TYPE_INSN_ARRAY)
> -			bpf_insn_array_adjust(map, off, len);
> -	}
> -#endif
> -}
> -
>  /* Now this function is used only to blind the main prog and must be invoked only when
>   * bpf_prog_need_blind() returns true.
>   */
> @@ -1577,12 +1560,6 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bp
>  
>  		if (env)
>  			env->prog = clone;
> -		else
> -			/* Instructions arrays must be updated using absolute xlated offsets.
> -			 * The arrays have already been adjusted by bpf_patch_insn_data() when
> -			 * env is not NULL.
> -			 */
> -			adjust_insn_arrays(clone, i, rewritten);
>  
>  		/* Walk new program and skip insns we just inserted. */
>  		insn = clone->insnsi + i + insn_delta;
> @@ -2551,47 +2528,63 @@ static bool bpf_prog_select_interpreter(struct bpf_prog *fp)
>  	return select_interpreter;
>  }
>  
> -static struct bpf_prog *bpf_prog_jit_compile(struct bpf_prog *prog)
> +static struct bpf_prog *bpf_prog_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  #ifdef CONFIG_BPF_JIT
>  	bool blinded = false;
>  	struct bpf_prog *orig_prog = prog;
> +	struct bpf_insn_aux_data *orig_insn_aux;
>  
>  	if (bpf_prog_need_blind(orig_prog)) {
> -		prog = bpf_jit_blind_constants(NULL, orig_prog);
> +		if (env) {
> +			/* If env is not NULL, we are called from the end of bpf_check(), at this
> +			 * point, only insn_aux_data is used after failure, so we only restore it
> +			 * here.
> +			 */
> +			orig_insn_aux = bpf_dup_insn_aux_data(env);
> +			if (!orig_insn_aux)
> +				return orig_prog;
> +		}
> +		prog = bpf_jit_blind_constants(env, orig_prog);
>  		/* If blinding was requested and we failed during blinding, we must fall
>  		 * back to the interpreter.
>  		 */
> -		if (IS_ERR(prog))
> -			return orig_prog;
> +		if (IS_ERR(prog)) {
> +			prog = orig_prog;
> +			if (env)
> +				goto out_restore;
> +			else
> +				return prog;
> +		}
>  		blinded = true;
>  	}
>  
> -	prog = bpf_int_jit_compile(prog);
> +	prog = bpf_int_jit_compile(env, prog);
>  	if (blinded) {
>  		if (!prog->jited) {
>  			bpf_jit_prog_release_other(orig_prog, prog);
>  			prog = orig_prog;
> +			if (env)
> +				goto out_restore;
>  		} else {
>  			bpf_jit_prog_release_other(prog, orig_prog);
> +			if (env)
> +				goto out_free;
>  		}
>  	}
> +
> +	return prog;
> +
> +out_restore:
> +	bpf_restore_insn_aux_data(env, orig_insn_aux);
> +out_free:
> +	kvfree(orig_insn_aux);
>  #endif
>  	return prog;
>  }
>  
> -/**
> - *	bpf_prog_select_runtime - select exec runtime for BPF program
> - *	@fp: bpf_prog populated with BPF program
> - *	@err: pointer to error variable
> - *
> - * Try to JIT eBPF program, if JIT is not available, use interpreter.
> - * The BPF program will be executed via bpf_prog_run() function.
> - *
> - * Return: the &fp argument along with &err set to 0 for success or
> - * a negative errno code on failure
> - */
> -struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
> +struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct bpf_prog *fp,
> +					   int *err)
>  {
>  	/* In case of BPF to BPF calls, verifier did all the prep
>  	 * work with regards to JITing, etc.
> @@ -2619,7 +2612,7 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
>  		if (*err)
>  			return fp;
>  
> -		fp = bpf_prog_jit_compile(fp);
> +		fp = bpf_prog_jit_compile(env, fp);
>  		bpf_prog_jit_attempt_done(fp);
>  		if (!fp->jited && jit_needed) {
>  			*err = -ENOTSUPP;
> @@ -2645,6 +2638,22 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
>  
>  	return fp;
>  }
> +
> +/**
> + *	bpf_prog_select_runtime - select exec runtime for BPF program
> + *	@fp: bpf_prog populated with BPF program
> + *	@err: pointer to error variable
> + *
> + * Try to JIT eBPF program, if JIT is not available, use interpreter.
> + * The BPF program will be executed via bpf_prog_run() function.
> + *
> + * Return: the &fp argument along with &err set to 0 for success or
> + * a negative errno code on failure
> + */
> +struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
> +{
> +	return __bpf_prog_select_runtime(NULL, fp, err);
> +}
>  EXPORT_SYMBOL_GPL(bpf_prog_select_runtime);
>  
>  static unsigned int __bpf_prog_ret1(const void *ctx,
> @@ -3132,7 +3141,7 @@ const struct bpf_func_proto bpf_tail_call_proto = {
>   * It is encouraged to implement bpf_int_jit_compile() instead, so that
>   * eBPF and implicitly also cBPF can get JITed!
>   */
> -struct bpf_prog * __weak bpf_int_jit_compile(struct bpf_prog *prog)
> +struct bpf_prog * __weak bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_prog *prog)
>  {
>  	return prog;
>  }
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index e1505c9cd09e..553dca175640 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -3090,10 +3090,6 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
>  	if (err < 0)
>  		goto free_used_maps;
>  
> -	prog = bpf_prog_select_runtime(prog, &err);
> -	if (err < 0)
> -		goto free_used_maps;
> -
>  	err = bpf_prog_mark_insn_arrays_ready(prog);
>  	if (err < 0)
>  		goto free_used_maps;
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 66cef3744fde..5084a754a748 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -22983,7 +22983,7 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
>  	return 0;
>  }
>  
> -static u32 *dup_subprog_starts(struct bpf_verifier_env *env)
> +static u32 *bpf_dup_subprog_starts(struct bpf_verifier_env *env)
>  {
>  	u32 *starts = NULL;
>  
> @@ -22995,13 +22995,13 @@ static u32 *dup_subprog_starts(struct bpf_verifier_env *env)
>  	return starts;
>  }
>  
> -static void restore_subprog_starts(struct bpf_verifier_env *env, u32 *orig_starts)
> +static void bpf_restore_subprog_starts(struct bpf_verifier_env *env, u32 *orig_starts)
>  {
>  	for (int i = 0; i < env->subprog_cnt; i++)
>  		env->subprog_info[i].start = orig_starts[i];
>  }
>  
> -static struct bpf_insn_aux_data *dup_insn_aux_data(struct bpf_verifier_env *env)
> +struct bpf_insn_aux_data *bpf_dup_insn_aux_data(struct bpf_verifier_env *env)
>  {
>  	size_t size;
>  
> @@ -23009,8 +23009,8 @@ static struct bpf_insn_aux_data *dup_insn_aux_data(struct bpf_verifier_env *env)
>  	return kvmemdup(env->insn_aux_data, size, GFP_KERNEL_ACCOUNT);
>  }
>  
> -static void restore_insn_aux_data(struct bpf_verifier_env *env,
> -				  struct bpf_insn_aux_data *orig_insn_aux)
> +void bpf_restore_insn_aux_data(struct bpf_verifier_env *env,
> +			       struct bpf_insn_aux_data *orig_insn_aux)
>  {
>  	/* the expanded elements are zero-filled, so no special handling is required */
>  	vfree(env->insn_aux_data);
> @@ -23153,7 +23153,7 @@ static int __jit_subprogs(struct bpf_verifier_env *env)
>  		func[i]->aux->might_sleep = env->subprog_info[i].might_sleep;
>  		if (!i)
>  			func[i]->aux->exception_boundary = env->seen_exception;
> -		func[i] = bpf_int_jit_compile(func[i]);
> +		func[i] = bpf_int_jit_compile(env, func[i]);
>  		if (!func[i]->jited) {
>  			err = -ENOTSUPP;
>  			goto out_free;
> @@ -23197,7 +23197,7 @@ static int __jit_subprogs(struct bpf_verifier_env *env)
>  	}
>  	for (i = 0; i < env->subprog_cnt; i++) {
>  		old_bpf_func = func[i]->bpf_func;
> -		tmp = bpf_int_jit_compile(func[i]);
> +		tmp = bpf_int_jit_compile(env, func[i]);
>  		if (tmp != func[i] || func[i]->bpf_func != old_bpf_func) {
>  			verbose(env, "JIT doesn't support bpf-to-bpf calls\n");
>  			err = -ENOTSUPP;
> @@ -23297,12 +23297,12 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  
>  	prog = orig_prog = env->prog;
>  	if (bpf_prog_need_blind(orig_prog)) {
> -		orig_insn_aux = dup_insn_aux_data(env);
> +		orig_insn_aux = bpf_dup_insn_aux_data(env);
>  		if (!orig_insn_aux) {
>  			err = -ENOMEM;
>  			goto out_cleanup;
>  		}
> -		orig_subprog_starts = dup_subprog_starts(env);
> +		orig_subprog_starts = bpf_dup_subprog_starts(env);
>  		if (!orig_subprog_starts) {
>  			err = -ENOMEM;
>  			goto out_free_aux;
> @@ -23347,8 +23347,8 @@ static int jit_subprogs(struct bpf_verifier_env *env)
>  	return 0;
>  
>  out_restore:
> -	restore_subprog_starts(env, orig_subprog_starts);
> -	restore_insn_aux_data(env, orig_insn_aux);
> +	bpf_restore_subprog_starts(env, orig_subprog_starts);
> +	bpf_restore_insn_aux_data(env, orig_insn_aux);
>  	kvfree(orig_subprog_starts);
>  out_free_aux:
>  	kvfree(orig_insn_aux);
> @@ -26523,6 +26523,14 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
>  
>  	adjust_btf_func(env);
>  
> +	/* extension progs temporarily inherit the attach_type of their targets
> +	   for verification purposes, so set it back to zero before returning
> +	 */
> +	if (env->prog->type == BPF_PROG_TYPE_EXT)
> +		env->prog->expected_attach_type = 0;
> +
> +	env->prog = __bpf_prog_select_runtime(env, env->prog, &ret);
> +
>  err_release_maps:
>  	if (ret)
>  		release_insn_arrays(env);
> @@ -26534,12 +26542,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
>  	if (!env->prog->aux->used_btfs)
>  		release_btfs(env);
>  
> -	/* extension progs temporarily inherit the attach_type of their targets
> -	   for verification purposes, so set it back to zero before returning
> -	 */
> -	if (env->prog->type == BPF_PROG_TYPE_EXT)
> -		env->prog->expected_attach_type = 0;
> -
>  	*prog = env->prog;
>  
>  	module_put(env->attach_btf_mod);



^ permalink raw reply


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