Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH net-next 2/2] net: phy: Introduce Airoha AN8801/R Gigabit Ethernet PHY driver
From: Louis-Alexis Eyraud @ 2026-03-25 18:15 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	AngeloGioacchino Del Regno, Heiner Kallweit, Russell King,
	kevin-kw.huang, macpaul.lin, matthias.bgg, kernel, netdev,
	devicetree, linux-arm-kernel, linux-mediatek, linux-kernel
In-Reply-To: <3fbfabf7-b3af-405b-ade4-4f62db2c1c45@lunn.ch>

Hi Andrew,

On Wed, 2026-03-04 at 15:59 +0100, Andrew Lunn wrote:
> > +static int an8801r_did_interrupt(struct phy_device *phydev)
> > +{
> > +	u32 irq_en, irq_status;
> > +	int ret;
> > +
> > +	ret = air_buckpbus_reg_read(phydev,
> > AN8801_BPBUS_REG_WAKE_IRQ_EN,
> > +				    &irq_en);
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = air_buckpbus_reg_read(phydev,
> > AN8801_BPBUS_REG_WAKE_IRQ_STS,
> > +				    &irq_status);
> > +	if (ret)
> > +		return ret;
> > +
> > +	if (irq_status & AN8801_IRQ_WAKE_MAGICPKT)
> > +		return 0;
> 
> With a name like an8801r_did_interrupt() you would expect the return
> value to be some value of True, if there was an interrupt. I would
> suggest either a different name, or return 1. Maybe also add a
> kerneldoc header indicating the return values, since it is probably
> not going to be standard.
> 
The function name was not great and confusing.

While reworking the interrupt handling for WoL support for v2, I merged
the function with the an8801r_handle_interrupt function (to process
differently the Magic Packet and Link Change interrupts) so this
function won't be in v2.
 
> > +static void an8801r_get_wol(struct phy_device *phydev,
> > +			    struct ethtool_wolinfo *wol)
> > +{
> > +	u32 reg_val;
> > +
> > +	air_buckpbus_reg_read(phydev,
> > AN8801_BPBUS_REG_WAKEUP_CTL1, &reg_val);
> > +
> > +	wol->supported = WAKE_MAGIC;
> 
> How does WoL work on this device. Only via interrupts? If so, maybe
> you should only return WAKE_MAGIC as supported if there is a valid
> interrupt?
> 
Yes, the WoL works via interrupts and indeed it lacks the interrupt
validity check.

In v2, following the RTL8211F wake-on-lan support example given to me
by Russell in his review, I'll fix this by adding a check using
device_can_wakeup in an8801r_get_wol and an8801r_set_wol functions and
adding a probe function (there was none in v1) to mark the PHY device
as wakeup capable if it has a valid interrupt and if the wakeup-source
property is present in the devicetree for the device node.

> > +static int an8801r_rgmii_delay_config(struct phy_device *phydev)
> > +{
> > +	switch (phydev->interface) {
> > +	case PHY_INTERFACE_MODE_RGMII_TXID:
> > +		return an8801r_rgmii_txdelay(phydev, 4);
> > +	case PHY_INTERFACE_MODE_RGMII_RXID:
> > +		return an8801r_rgmii_rxdelay(phydev, 0);
> > +	case PHY_INTERFACE_MODE_RGMII_ID:
> > +		return an8801r_rgmii_txdelay(phydev, 4);
> > +		return an8801r_rgmii_rxdelay(phydev, 0);
> 
> The parameters look very odd here. 4 means 2ns, but 0 also means 0ns?
> Can this API be improved?
From the info I finally got about these magic values, the differences
between the RX and TX values for the default insert delays can be
explained by the additional RGMII_RXDELAY_ALIGN bit setting when
writing the RX delay register (AN8801_BPBUS_REG_RXDLY_STEP), done by
an8801r_rgmii_rxdelay function because it adds an extra offset.

For TX, the 4 value is the delay step value that is the closest to 2ns
(1.883ns). But For RX, setting the step value to 0 and setting the
RGMII_RXDELAY_ALIGN bit too, inserts a 1.992ns delay. Without align
bit, it would indeed be -0.008ns.

Those delays are also inserted because the an8801r_rgmii_rxdelay and
an8801r_rgmii_txdelay function set the force mode bit
(RGMII_RXDELAY_FORCE_MODE / RGMII_TXDELAY_FORCE_MODE). 
If this bit is unset, it prevents inserting a delay.

> Also, PHY_INTERFACE_MODE_RGMII_TXID means 2ns delay for TX, but it
> also means 0ns delay for RX. The code appears to be missing this
> second part.
> 
There is indeed a bug with this double return in
PHY_INTERFACE_MODE_RGMII_ID case so the RX delay is not inserted.

> > +	case PHY_INTERFACE_MODE_RGMII:
> 
> And here you should be disabling all delays. We have seen boards
> where
> the strapping is wrong, the PHY boots in RGMII_ID, but RGMII is
> required, and so the driver must fully implement
> PHY_INTERFACE_MODE_RGMII disabling the delays.
> 
You're right it is also missing the delay disabling part.

The an8801r_rgmii_txdelay and an8801r_rgmii_rxdelay function don't
allow to disable them since they always set force mode bit and because
the 0 values does not completely mean no inserted delay.
Their implementations should be modify to be able to do that.

For v2, I've reworked the an8801r_rgmii_delay_config and
an8801r_rgmii_rx/txdelay to handle properly all RGMII configuration
cases and I hope in a simpler manner.

> > +static int an8801r_config_init(struct phy_device *phydev)
> > +{
> > +	u8 led_default_function[AN8801R_NUM_LEDS] = { 0 };
> > +	int prev_page, ret;
> > +
> > +	ret = an8801r_of_init_leds(phydev, led_default_function);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Disable Low Power Mode (LPM) */
> > +	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
> > AN8801_REG_PHY_INTERNAL0,
> > +			    FIELD_PREP(AN8801_PHY_INTFUNC_MASK,
> > 0x1e));
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
> > AN8801_REG_PHY_INTERNAL1,
> > +			    FIELD_PREP(AN8801_PHY_INTFUNC_MASK,
> > 0x2));
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* Disable EEE by default */
> > +	ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV,
> > 0);
> > +	if (ret)
> > +		return ret;
> 
> Why? If EEE is broken, this is not sufficient to stop a user
> re-enabling it.
> 
I've tested by removing these lines and EEE seems working fine.
I'll remove them in v2.

> > +static int an8801r_read_status(struct phy_device *phydev)
> > +{
> > +	int prev_speed, ret;
> > +	u32 val;
> > +
> > +	prev_speed = phydev->speed;
> > +
> > +	ret = genphy_read_status(phydev);
> > +	if (ret)
> > +		return ret;
> 
> You configure the PHY to support downshift. If it has performed a
> downshift, does it report the actual speed in the usual registers
> read
> by genphy_read_status(), or is it necessary to read a vendor
> register?
From the tests I've done, I got the actual speed read correctly by
genphy_read_status function.
I did a test by adding in this function the vendor register reading at
the same time and comparing it and did not get a discrepancy too when
switching with ethtool between different speed configurations.

Would it be more reliable to use the vendor register instead?

> 
> > +static struct phy_driver airoha_driver[] = {
> > +{
> > +	PHY_ID_MATCH_MODEL(AN8801R_PHY_ID),
> > +	.name			= "Airoha AN8801R",
> > +	.features		= PHY_GBIT_FEATURES,
> 
> Should not be needed, if the PHY enumerates its capabilities
> correctly.
I confirm it is not needed, I'll remove it in v2.

Thanks for the review.

Regards,
Louis-Alexis

> 
>     Andrew
> 
> ---
> pw-bot: cr


^ permalink raw reply

* Re: [PATCH 3/3] arm64: dts: freescale: imx95-toradex-smarc: Use gpio-hog for WIFI_UART_EN
From: Francesco Dolcini @ 2026-03-25 18:10 UTC (permalink / raw)
  To: Frank Li
  Cc: Franz Schnyder, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam,
	Franz Schnyder, devicetree, imx, linux-arm-kernel, linux-kernel,
	Francesco Dolcini
In-Reply-To: <acP3NiGvRCc1SgjE@lizhi-Precision-Tower-5810>

On Wed, Mar 25, 2026 at 10:54:46AM -0400, Frank Li wrote:
> On Wed, Mar 25, 2026 at 12:55:11PM +0100, Franz Schnyder wrote:
> > From: Franz Schnyder <franz.schnyder@toradex.com>
> >
> > On the Toradex SMARC iMX95, the WiFi UART signals are shared with the
> > JTAG. The WIFI_UART_EN signal is used to select between these
> > two functions.
> >
> > Configure the signal as gpio-hog and drive it high to select the UART
> > function by default. Add a label to override the hog in derived
> > device trees.
> 
> gpio hog have problem about probe order, are you sure gpio device probe
> before pcie?

This is not about PCIe, we are talking about UART here. Specifically the
module is a combo Wi-Fi/BT device, with Wi-Fi over SDIO, and BT over
UART from NXP.

In any case, this DT is going to be used also by the boot firmware that will
configure the GPIO hog way before the Linux driver probes.

The DT files from the Linux kernel are used also by other projects.

> I have not seen any place refer to wifi_uart_en.

There is none (as of now). This is there to make it easier for a user
that needs access to debug to adjust this node enabling the JTAG
functionality.

Francesco



^ permalink raw reply

* Re: [PATCH v3 2/9] media: dt-bindings: add rockchip rk3588 vicap
From: Conor Dooley @ 2026-03-25 18:06 UTC (permalink / raw)
  To: michael.riesch
  Cc: Mehdi Djait, Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, Kever Yang,
	Jagan Teki,
	Кузнецов Михаил,
	Charalampos Mitrodimas, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus, linux-media, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20250430-rk3588-vicap-v3-2-e38e428868cc@collabora.com>

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

Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable

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

^ permalink raw reply

* Re: [PATCH v7 0/2] Add support for Variscite DART-MX95 and Sonata board
From: Francesco Dolcini @ 2026-03-25 18:06 UTC (permalink / raw)
  To: Frank Li
  Cc: Francesco Dolcini, Stefano Radaelli, devicetree, linux-kernel,
	pierluigi.p, Stefano Radaelli, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, imx, linux-arm-kernel
In-Reply-To: <acP2UX6B5js_ozWm@lizhi-Precision-Tower-5810>

On Wed, Mar 25, 2026 at 10:50:57AM -0400, Frank Li wrote:
> On Wed, Mar 25, 2026 at 01:21:04PM +0100, Francesco Dolcini wrote:
> > On Tue, Mar 24, 2026 at 03:48:29PM -0400, Frank Li wrote:
> > > On Fri, Mar 13, 2026 at 02:56:03PM -0400, Frank Li wrote:
> > > > On Fri, Mar 13, 2026 at 06:47:01PM +0100, Stefano Radaelli wrote:
> > > > > This patch series adds support for the Variscite DART-MX95 system on
> > > > > module and the Sonata carrier board.
> > > > >
> > > > > The series includes:
> > > > > - Device tree bindings documentation for both SOM and carrier board
> > > > > - SOM device tree with on-module peripherals
> > > > > - Sonata carrier board device tree with board-specific features
> > > > >
> > > > > The implementation follows the standard SOM + carrier board pattern
> > > > > where the SOM dtsi contains only peripherals mounted on the module,
> > > > > while carrier-specific interfaces are enabled in the board dts.
> > > > >
> > > > > v7:
> > > > > - Order nodes in symphony dts
> > > >
> > > > Can you run https://github.com/lznuaa/dt-format for new file to easy
> > > > track and check by script later.
> > >
> > > I applied with below change
> > > - update copywrite to 2026
> >
> > How do you know that the correct copyright year is 2026?
> > The copyright years does not change to today just because it is the year
> > it was submitted.
> 
> At least it should include 2026 because it is new files in kernel
> tree.

The copyright year is not changing nor being updated just because you
are adding the file to the linux kernel tree.

Francesco




^ permalink raw reply

* Re: [PATCH v3 4/5] KVM: arm64: Enable HDBSS support and handle HDBSSF events
From: Leonardo Bras @ 2026-03-25 18:05 UTC (permalink / raw)
  To: Tian Zheng
  Cc: Leonardo Bras, maz, oupton, catalin.marinas, corbet, pbonzini,
	will, yuzenghui, wangzhou1, liuyonglong, Jonathan.Cameron,
	yezhenyu2, linuxarm, joey.gouly, kvmarm, kvm, linux-arm-kernel,
	linux-doc, linux-kernel, skhan, suzuki.poulose
In-Reply-To: <20260225040421.2683931-5-zhengtian10@huawei.com>

Hello Tian,

I am currently working on HACDBS enablement(which will be rebased on top of 
this patchset) and due to the fact HACDBS and HDBSS are kind of 
complementary I will sometimes come with some questions for issues I have 
faced myself on that part. :)

(see below)

On Wed, Feb 25, 2026 at 12:04:20PM +0800, Tian Zheng wrote:
> From: eillon <yezhenyu2@huawei.com>
> 
> HDBSS is enabled via an ioctl from userspace (e.g. QEMU) at the start of
> migration. This feature is only supported in VHE mode.
> 
> Initially, S2 PTEs doesn't contain the DBM attribute. During migration,
> write faults are handled by user_mem_abort, which relaxes permissions
> and adds the DBM bit when HDBSS is active. Once DBM is set, subsequent
> writes no longer trap, as the hardware automatically transitions the page
> from writable-clean to writable-dirty.
> 
> KVM does not scan S2 page tables to consume DBM. Instead, when HDBSS is
> enabled, the hardware observes the clean->dirty transition and records
> the corresponding page into the HDBSS buffer.
> 
> During sync_dirty_log, KVM kicks all vCPUs to force VM-Exit, ensuring
> that check_vcpu_requests flushes the HDBSS buffer and propagates the
> accumulated dirty information into the userspace-visible dirty bitmap.
> 
> Add fault handling for HDBSS including buffer full, external abort, and
> general protection fault (GPF).
> 
> Signed-off-by: eillon <yezhenyu2@huawei.com>
> Signed-off-by: Tian Zheng <zhengtian10@huawei.com>
> ---
>  arch/arm64/include/asm/esr.h      |   5 ++
>  arch/arm64/include/asm/kvm_host.h |  17 +++++
>  arch/arm64/include/asm/kvm_mmu.h  |   1 +
>  arch/arm64/include/asm/sysreg.h   |  11 ++++
>  arch/arm64/kvm/arm.c              | 102 ++++++++++++++++++++++++++++++
>  arch/arm64/kvm/hyp/vhe/switch.c   |  19 ++++++
>  arch/arm64/kvm/mmu.c              |  70 ++++++++++++++++++++
>  arch/arm64/kvm/reset.c            |   3 +
>  8 files changed, 228 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index 81c17320a588..2e6b679b5908 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -437,6 +437,11 @@
>  #ifndef __ASSEMBLER__
>  #include <asm/types.h>
> 
> +static inline bool esr_iss2_is_hdbssf(unsigned long esr)
> +{
> +	return ESR_ELx_ISS2(esr) & ESR_ELx_HDBSSF;
> +}
> +
>  static inline unsigned long esr_brk_comment(unsigned long esr)
>  {
>  	return esr & ESR_ELx_BRK64_ISS_COMMENT_MASK;
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 5d5a3bbdb95e..57ee6b53e061 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -55,12 +55,17 @@
>  #define KVM_REQ_GUEST_HYP_IRQ_PENDING	KVM_ARCH_REQ(9)
>  #define KVM_REQ_MAP_L1_VNCR_EL2		KVM_ARCH_REQ(10)
>  #define KVM_REQ_VGIC_PROCESS_UPDATE	KVM_ARCH_REQ(11)
> +#define KVM_REQ_FLUSH_HDBSS			KVM_ARCH_REQ(12)
> 
>  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
>  				     KVM_DIRTY_LOG_INITIALLY_SET)
> 
>  #define KVM_HAVE_MMU_RWLOCK
> 
> +/* HDBSS entry field definitions */
> +#define HDBSS_ENTRY_VALID BIT(0)
> +#define HDBSS_ENTRY_IPA GENMASK_ULL(55, 12)
> +
>  /*
>   * Mode of operation configurable with kvm-arm.mode early param.
>   * See Documentation/admin-guide/kernel-parameters.txt for more information.
> @@ -84,6 +89,7 @@ int __init kvm_arm_init_sve(void);
>  u32 __attribute_const__ kvm_target_cpu(void);
>  void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
>  void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
> +void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu);
> 
>  struct kvm_hyp_memcache {
>  	phys_addr_t head;
> @@ -405,6 +411,8 @@ struct kvm_arch {
>  	 * the associated pKVM instance in the hypervisor.
>  	 */
>  	struct kvm_protected_vm pkvm;
> +
> +	bool enable_hdbss;
>  };
> 
>  struct kvm_vcpu_fault_info {
> @@ -816,6 +824,12 @@ struct vcpu_reset_state {
>  	bool		reset;
>  };
> 
> +struct vcpu_hdbss_state {
> +	phys_addr_t base_phys;
> +	u32 size;
> +	u32 next_index;
> +};
> +
>  struct vncr_tlb;
> 
>  struct kvm_vcpu_arch {
> @@ -920,6 +934,9 @@ struct kvm_vcpu_arch {
> 
>  	/* Per-vcpu TLB for VNCR_EL2 -- NULL when !NV */
>  	struct vncr_tlb	*vncr_tlb;
> +
> +	/* HDBSS registers info */
> +	struct vcpu_hdbss_state hdbss;
>  };
> 
>  /*
> diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
> index d968aca0461a..3fea8cfe8869 100644
> --- a/arch/arm64/include/asm/kvm_mmu.h
> +++ b/arch/arm64/include/asm/kvm_mmu.h
> @@ -183,6 +183,7 @@ int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
> 
>  int kvm_handle_guest_sea(struct kvm_vcpu *vcpu);
>  int kvm_handle_guest_abort(struct kvm_vcpu *vcpu);
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu);
> 
>  phys_addr_t kvm_mmu_get_httbr(void);
>  phys_addr_t kvm_get_idmap_vector(void);
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index f4436ecc630c..d11f4d0dd4e7 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -1039,6 +1039,17 @@
> 
>  #define GCS_CAP(x)	((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \
>  					       GCS_CAP_VALID_TOKEN)
> +
> +/*
> + * Definitions for the HDBSS feature
> + */
> +#define HDBSS_MAX_SIZE		HDBSSBR_EL2_SZ_2MB
> +
> +#define HDBSSBR_EL2(baddr, sz)	(((baddr) & GENMASK(55, 12 + sz)) | \
> +				 FIELD_PREP(HDBSSBR_EL2_SZ_MASK, sz))
> +
> +#define HDBSSPROD_IDX(prod)	FIELD_GET(HDBSSPROD_EL2_INDEX_MASK, prod)
> +
>  /*
>   * Definitions for GICv5 instructions]
>   */
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 29f0326f7e00..d64da05e25c4 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -125,6 +125,87 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
>  	return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
>  }
> 
> +void kvm_arm_vcpu_free_hdbss(struct kvm_vcpu *vcpu)
> +{
> +	struct page *hdbss_pg;
> +
> +	hdbss_pg = phys_to_page(vcpu->arch.hdbss.base_phys);
> +	if (hdbss_pg)
> +		__free_pages(hdbss_pg, vcpu->arch.hdbss.size);
> +
> +	vcpu->arch.hdbss.size = 0;
> +}
> +
> +static int kvm_cap_arm_enable_hdbss(struct kvm *kvm,
> +				    struct kvm_enable_cap *cap)
> +{
> +	unsigned long i;
> +	struct kvm_vcpu *vcpu;
> +	struct page *hdbss_pg = NULL;
> +	__u64 size = cap->args[0];
> +	bool enable = cap->args[1] ? true : false;
> +
> +	if (!system_supports_hdbss())
> +		return -EINVAL;
> +
> +	if (size > HDBSS_MAX_SIZE)
> +		return -EINVAL;
> +
> +	if (!enable && !kvm->arch.enable_hdbss) /* Already Off */
> +		return 0;
> +
> +	if (enable && kvm->arch.enable_hdbss) /* Already On, can't set size */
> +		return -EINVAL;
> +
> +	if (!enable) { /* Turn it off */
> +		kvm->arch.mmu.vtcr &= ~(VTCR_EL2_HD | VTCR_EL2_HDBSS | VTCR_EL2_HA);
> +
> +		kvm_for_each_vcpu(i, vcpu, kvm) {
> +			/* Kick vcpus to flush hdbss buffer. */
> +			kvm_vcpu_kick(vcpu);
> +
> +			kvm_arm_vcpu_free_hdbss(vcpu);
> +		}
> +
> +		kvm->arch.enable_hdbss = false;
> +
> +		return 0;
> +	}
> +
> +	/* Turn it on */
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		hdbss_pg = alloc_pages(GFP_KERNEL_ACCOUNT, size);
> +		if (!hdbss_pg)
> +			goto error_alloc;
> +
> +		vcpu->arch.hdbss = (struct vcpu_hdbss_state) {
> +			.base_phys = page_to_phys(hdbss_pg),
> +			.size = size,
> +			.next_index = 0,
> +		};
> +	}
> +
> +	kvm->arch.enable_hdbss = true;
> +	kvm->arch.mmu.vtcr |= VTCR_EL2_HD | VTCR_EL2_HDBSS | VTCR_EL2_HA;
> +
> +	/*
> +	 * We should kick vcpus out of guest mode here to load new
> +	 * vtcr value to vtcr_el2 register when re-enter guest mode.
> +	 */
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		kvm_vcpu_kick(vcpu);
> +
> +	return 0;
> +
> +error_alloc:
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		if (vcpu->arch.hdbss.base_phys)
> +			kvm_arm_vcpu_free_hdbss(vcpu);
> +	}
> +
> +	return -ENOMEM;
> +}
> +
>  int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  			    struct kvm_enable_cap *cap)
>  {
> @@ -182,6 +263,11 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
>  		r = 0;
>  		set_bit(KVM_ARCH_FLAG_EXIT_SEA, &kvm->arch.flags);
>  		break;
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		mutex_lock(&kvm->lock);
> +		r = kvm_cap_arm_enable_hdbss(kvm, cap);
> +		mutex_unlock(&kvm->lock);
> +		break;
>  	default:
>  		break;
>  	}
> @@ -471,6 +557,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
>  			r = kvm_supports_cacheable_pfnmap();
>  		break;
> 
> +	case KVM_CAP_ARM_HW_DIRTY_STATE_TRACK:
> +		r = system_supports_hdbss();
> +		break;
>  	default:
>  		r = 0;
>  	}
> @@ -1120,6 +1209,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>  		if (kvm_dirty_ring_check_request(vcpu))
>  			return 0;
> 
> +		if (kvm_check_request(KVM_REQ_FLUSH_HDBSS, vcpu))
> +			kvm_flush_hdbss_buffer(vcpu);
> +
>  		check_nested_vcpu_requests(vcpu);
>  	}
> 
> @@ -1898,7 +1990,17 @@ long kvm_arch_vcpu_unlocked_ioctl(struct file *filp, unsigned int ioctl,
> 
>  void kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
>  {
> +	/*
> +	 * Flush all CPUs' dirty log buffers to the dirty_bitmap.  Called
> +	 * before reporting dirty_bitmap to userspace. Send a request with
> +	 * KVM_REQUEST_WAIT to flush buffer synchronously.
> +	 */
> +	struct kvm_vcpu *vcpu;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> 
> +	kvm_make_all_cpus_request(kvm, KVM_REQ_FLUSH_HDBSS);
>  }
> 
>  static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c
> index 9db3f11a4754..600cbc4f8ae9 100644
> --- a/arch/arm64/kvm/hyp/vhe/switch.c
> +++ b/arch/arm64/kvm/hyp/vhe/switch.c
> @@ -213,6 +213,23 @@ static void __vcpu_put_deactivate_traps(struct kvm_vcpu *vcpu)
>  	local_irq_restore(flags);
>  }
> 
> +static void __load_hdbss(struct kvm_vcpu *vcpu)
> +{
> +	struct kvm *kvm = vcpu->kvm;
> +	u64 br_el2, prod_el2;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> +
> +	br_el2 = HDBSSBR_EL2(vcpu->arch.hdbss.base_phys, vcpu->arch.hdbss.size);
> +	prod_el2 = vcpu->arch.hdbss.next_index;
> +
> +	write_sysreg_s(br_el2, SYS_HDBSSBR_EL2);
> +	write_sysreg_s(prod_el2, SYS_HDBSSPROD_EL2);
> +
> +	isb();
> +}
> +

I see in the code below you trust that the tracking will happen with 
PAGE_SIZE granularity (you track with PAGE_SHIFT).

That may be a problem when we have guest memory backed by hugepages or 
transparent huge pages. 

When we are using HDBSS, there is no fault happening, so we have no way of 
doing on-demand block splitting, so we need to make use of eager block 
splitting, _before_ we start to track anything, or else we may have 
different-sized pages in the HDBSS buffer, which is harder to deal with.

Suggestion: do the eager splitting before we enable HDBSS. 

For this to happen, we have to enable the EAGER_SPLIT_CHUNK_SIZE 
capability, which can only be enabled when all memslots are empty.

I suggest doing that at kvm_init_stage2_mmu(), and checking if HDBSS is 
in which case we set mmu->split_page_chunk_size to PAGESIZE.

I will send a patch you can put before this one to make sure it works :)

Thanks!
Leo


>  void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
>  {
>  	host_data_ptr(host_ctxt)->__hyp_running_vcpu = vcpu;
> @@ -220,10 +237,12 @@ void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu)
>  	__vcpu_load_switch_sysregs(vcpu);
>  	__vcpu_load_activate_traps(vcpu);
>  	__load_stage2(vcpu->arch.hw_mmu, vcpu->arch.hw_mmu->arch);
> +	__load_hdbss(vcpu);
>  }
> 
>  void kvm_vcpu_put_vhe(struct kvm_vcpu *vcpu)
>  {
> +	kvm_flush_hdbss_buffer(vcpu);
>  	__vcpu_put_deactivate_traps(vcpu);
>  	__vcpu_put_switch_sysregs(vcpu);
> 
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 070a01e53fcb..42b0710a16ce 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1896,6 +1896,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
>  	if (writable)
>  		prot |= KVM_PGTABLE_PROT_W;
> 
> +	if (writable && kvm->arch.enable_hdbss && logging_active)
> +		prot |= KVM_PGTABLE_PROT_DBM;
> +
>  	if (exec_fault)
>  		prot |= KVM_PGTABLE_PROT_X;
> 
> @@ -2033,6 +2036,70 @@ int kvm_handle_guest_sea(struct kvm_vcpu *vcpu)
>  	return 0;
>  }
> 
> +void kvm_flush_hdbss_buffer(struct kvm_vcpu *vcpu)
> +{
> +	int idx, curr_idx;
> +	u64 br_el2;
> +	u64 *hdbss_buf;
> +	struct kvm *kvm = vcpu->kvm;
> +
> +	if (!kvm->arch.enable_hdbss)
> +		return;
> +
> +	curr_idx = HDBSSPROD_IDX(read_sysreg_s(SYS_HDBSSPROD_EL2));
> +	br_el2 = HDBSSBR_EL2(vcpu->arch.hdbss.base_phys, vcpu->arch.hdbss.size);
> +
> +	/* Do nothing if HDBSS buffer is empty or br_el2 is NULL */
> +	if (curr_idx == 0 || br_el2 == 0)
> +		return;
> +
> +	hdbss_buf = page_address(phys_to_page(vcpu->arch.hdbss.base_phys));
> +	if (!hdbss_buf)
> +		return;
> +
> +	guard(write_lock_irqsave)(&vcpu->kvm->mmu_lock);
> +	for (idx = 0; idx < curr_idx; idx++) {
> +		u64 gpa;
> +
> +		gpa = hdbss_buf[idx];
> +		if (!(gpa & HDBSS_ENTRY_VALID))
> +			continue;
> +
> +		gpa &= HDBSS_ENTRY_IPA;
> +		kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
> +	}

Here ^

> +
> +	/* reset HDBSS index */
> +	write_sysreg_s(0, SYS_HDBSSPROD_EL2);
> +	vcpu->arch.hdbss.next_index = 0;
> +	isb();
> +}
> +
> +static int kvm_handle_hdbss_fault(struct kvm_vcpu *vcpu)
> +{
> +	u64 prod;
> +	u64 fsc;
> +
> +	prod = read_sysreg_s(SYS_HDBSSPROD_EL2);
> +	fsc = FIELD_GET(HDBSSPROD_EL2_FSC_MASK, prod);
> +
> +	switch (fsc) {
> +	case HDBSSPROD_EL2_FSC_OK:
> +		/* Buffer full, which is reported as permission fault. */
> +		kvm_flush_hdbss_buffer(vcpu);
> +		return 1;
> +	case HDBSSPROD_EL2_FSC_ExternalAbort:
> +	case HDBSSPROD_EL2_FSC_GPF:
> +		return -EFAULT;
> +	default:
> +		/* Unknown fault. */
> +		WARN_ONCE(1,
> +				"Unexpected HDBSS fault type, FSC: 0x%llx (prod=0x%llx, vcpu=%d)\n",
> +				fsc, prod, vcpu->vcpu_id);
> +		return -EFAULT;
> +	}
> +}
> +
>  /**
>   * kvm_handle_guest_abort - handles all 2nd stage aborts
>   * @vcpu:	the VCPU pointer
> @@ -2071,6 +2138,9 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
> 
>  	is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
> 
> +	if (esr_iss2_is_hdbssf(esr))
> +		return kvm_handle_hdbss_fault(vcpu);
> +
>  	if (esr_fsc_is_translation_fault(esr)) {
>  		/* Beyond sanitised PARange (which is the IPA limit) */
>  		if (fault_ipa >= BIT_ULL(get_kvm_ipa_limit())) {
> diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
> index 959532422d3a..c03a4b310b53 100644
> --- a/arch/arm64/kvm/reset.c
> +++ b/arch/arm64/kvm/reset.c
> @@ -161,6 +161,9 @@ void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu)
>  	free_page((unsigned long)vcpu->arch.ctxt.vncr_array);
>  	kfree(vcpu->arch.vncr_tlb);
>  	kfree(vcpu->arch.ccsidr);
> +
> +	if (vcpu->kvm->arch.enable_hdbss)
> +		kvm_arm_vcpu_free_hdbss(vcpu);
>  }
> 
>  static void kvm_vcpu_reset_sve(struct kvm_vcpu *vcpu)
> --
> 2.33.0
> 


^ permalink raw reply

* Re: [PATCH net-next v5 3/3] riscv: dts: eswin: eic7700-hifive-premier-p550: enable Ethernet controller
From: Simon Horman @ 2026-03-25 18:03 UTC (permalink / raw)
  To: lizhi2
  Cc: devicetree, andrew+netdev, davem, edumazet, kuba, robh, krzk+dt,
	conor+dt, netdev, pabeni, mcoquelin.stm32, alexandre.torgue,
	rmk+kernel, pjw, palmer, aou, alex, linux-riscv, linux-stm32,
	linux-arm-kernel, linux-kernel, maxime.chevallier, ningyu, linmin,
	pinkesh.vaghela, pritesh.patel, weishangjuan
In-Reply-To: <20260324073408.439-1-lizhi2@eswincomputing.com>

On Tue, Mar 24, 2026 at 03:34:08PM +0800, lizhi2@eswincomputing.com wrote:
> From: Zhi Li <lizhi2@eswincomputing.com>
> 
> Enable the on-board Gigabit Ethernet controller on the
> HiFive Premier P550 development board.
> 
> Signed-off-by: Zhi Li <lizhi2@eswincomputing.com>
> ---
>  .../dts/eswin/eic7700-hifive-premier-p550.dts | 42 ++++++++++++
>  arch/riscv/boot/dts/eswin/eic7700.dtsi        | 66 +++++++++++++++++++
>  2 files changed, 108 insertions(+)

Unfortunately this does not compile:

$ ARCH=riscv make allmodconfig dtbs
...
  DTC     arch/riscv/boot/dts/eswin/eic7700-hifive-premier-p550.dtb
arch/riscv/boot/dts/eswin/eic7700.dtsi:300.28-330.5: ERROR (phandle_references): /soc/ethernet@50400000: Reference to non-existent node or label "clk"
...

-- 
pw-bot: changes-requested


^ permalink raw reply

* Re: [PATCH v2 01/11] arm64: Skip update of an idreg field affected by an override
From: Catalin Marinas @ 2026-03-25 17:51 UTC (permalink / raw)
  To: Suzuki K Poulose
  Cc: Marc Zyngier, linux-arm-kernel, kvmarm, Fuad Tabba, Will Deacon,
	Mark Rutland, Joey Gouly, Oliver Upton, Zenghui Yu
In-Reply-To: <a35839df-74a0-46b3-b5e8-7e0a066b210d@arm.com>

On Wed, Mar 25, 2026 at 02:54:28PM +0000, Suzuki K Poulose wrote:
> On 19/03/2026 15:34, Catalin Marinas wrote:
> > On Mon, Mar 02, 2026 at 11:56:42AM +0000, Marc Zyngier wrote:
> > > When computing the new value od an idreg that contains a field
> > > affected by an override, do not update that particular field.
> > > 
> > > The value computed at init-time must be kept as-is, as that's
> > > what the user has asked for, for better or worse.
> > > 
> > > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > > ---
> > >   arch/arm64/kernel/cpufeature.c | 7 +++++++
> > >   1 file changed, 7 insertions(+)
> > > 
> > > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > > index c31f8e17732a3..28fc77443ccd3 100644
> > > --- a/arch/arm64/kernel/cpufeature.c
> > > +++ b/arch/arm64/kernel/cpufeature.c
> > > @@ -1224,6 +1224,13 @@ static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
> > >   		s64 ftr_cur = arm64_ftr_value(ftrp, reg->sys_val);
> > >   		s64 ftr_new = arm64_ftr_value(ftrp, new);
> > > +		/*
> > > +		 * Don't alter the initial value that has been forced
> > > +		 * by an override.
> > > +		 */
> > > +		if ((reg->override->mask & arm64_ftr_mask(ftrp)) == arm64_ftr_mask(ftrp))
> > > +			continue;
> > 
> > I got lost in the in the cpufeature framework, so I may be missing
> > something.
> > 
> > Let's say the primary CPU has a feature field with value 2 and we want
> > to override it to value 1. For e.g. a LOWER_SAFE feature, boot_cpu_data
> > will stored the overridden value of 1.
> > 
> > A secondary CPU comes online with the same feature missing, so value 0.
> > With the above change, we no longer update the system-wide feature
> > value, leave it as 1. Later on, for a system feature we may turn it on
> > even though the secondary CPU does not support it.
> > 
> > In summary, this makes the overridden field sticky for secondary CPUs
> > even if they don't support it.
> 
> That is true. I think we should let the secondary CPUs alter the values,
> with initial CPU feature value with the override value set, the system
> could then choose the safest among the override and the others.

It works for me. We should add a comment somewhere that the override is
not expected to work for features where we allow differences (some
FTR_NONSTRICT).

> > Unrelated to your patch, I think we can similarly fail to reject
> > secondary CPUs in check_early_cpu_features() -> verify_local_cpu_caps()
> > because of __read_sysreg_by_encoding() which uses the override value
> > unconditionally. From this perspective, we are now consistent with your
> > patch above.
> 
> This is true as well and the override takes the priority and with the
> wrong level of override value the system could be made to think that
> some features are available even when it is unsafe to do so.
> We should sanitise the values read by __read_sysreg_by_encoding() with
> the "overrides". I can cook something up.

Or remove this check if we expect the override to only work on the
resulting sanitised value, not individual checks.

-- 
Catalin


^ permalink raw reply

* [PATCH] soc: brcmstb: consolidate initcall functions
From: justin.chen @ 2026-03-25 17:46 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: kees, bcm-kernel-feedback-list, florian.fainelli, Justin Chen

From: Justin Chen <justin.chen@broadcom.com>

Merge the separate early_initcall and arch_initcall functions into a
single early_initcall. This is possible thanks to commit 6e12db376b60
("base: soc: Allow early registration of a single SoC device"), which
allows soc_device_register() to be called during early_initcall by
deferring the actual registration until the soc_bus is ready.

Replace static family_id/product_id variables with a dynamically
allocated brcmstb_soc_info structure.

Signed-off-by: Justin Chen <justin.chen@broadcom.com>
---
 drivers/soc/bcm/brcmstb/common.c | 88 +++++++++++++++++---------------
 1 file changed, 46 insertions(+), 42 deletions(-)

diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 2da79bd42930..7be0374f5943 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -11,18 +11,22 @@
 #include <linux/soc/brcmstb/brcmstb.h>
 #include <linux/sys_soc.h>
 
-static u32 family_id;
-static u32 product_id;
+struct brcmstb_soc_info {
+	u32 family_id;
+	u32 product_id;
+};
+
+static struct brcmstb_soc_info *soc_info;
 
 u32 brcmstb_get_family_id(void)
 {
-	return family_id;
+	return soc_info ? soc_info->family_id : 0;
 }
 EXPORT_SYMBOL(brcmstb_get_family_id);
 
 u32 brcmstb_get_product_id(void)
 {
-	return product_id;
+	return soc_info ? soc_info->product_id : 0;
 }
 EXPORT_SYMBOL(brcmstb_get_product_id);
 
@@ -40,10 +44,12 @@ static const struct of_device_id sun_top_ctrl_match[] = {
 	{ }
 };
 
-static int __init brcmstb_soc_device_early_init(void)
+static int __init brcmstb_soc_device_init(void)
 {
+	struct soc_device_attribute *soc_dev_attr;
 	struct device_node *sun_top_ctrl;
 	void __iomem *sun_top_ctrl_base;
+	struct soc_device *soc_dev;
 	int ret = 0;
 
 	/* We could be on a multi-platform kernel, don't make this fatal but
@@ -51,63 +57,61 @@ static int __init brcmstb_soc_device_early_init(void)
 	 */
 	sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
 	if (!sun_top_ctrl)
-		return ret;
+		return 0;
 
 	sun_top_ctrl_base = of_iomap(sun_top_ctrl, 0);
 	if (!sun_top_ctrl_base) {
 		ret = -ENODEV;
-		goto out;
+		goto out_put_node;
 	}
 
-	family_id = readl(sun_top_ctrl_base);
-	product_id = readl(sun_top_ctrl_base + 0x4);
-	iounmap(sun_top_ctrl_base);
-out:
-	of_node_put(sun_top_ctrl);
-	return ret;
-}
-early_initcall(brcmstb_soc_device_early_init);
-
-static int __init brcmstb_soc_device_init(void)
-{
-	struct soc_device_attribute *soc_dev_attr;
-	struct device_node *sun_top_ctrl;
-	struct soc_device *soc_dev;
-	int ret = 0;
+	soc_info = kzalloc(sizeof(*soc_info), GFP_KERNEL);
+	if (!soc_info) {
+		ret = -ENOMEM;
+		goto out_unmap;
+	}
 
-	/* We could be on a multi-platform kernel, don't make this fatal but
-	 * bail out early
-	 */
-	sun_top_ctrl = of_find_matching_node(NULL, sun_top_ctrl_match);
-	if (!sun_top_ctrl)
-		return ret;
+	soc_info->family_id = readl(sun_top_ctrl_base);
+	soc_info->product_id = readl(sun_top_ctrl_base + 0x4);
 
 	soc_dev_attr = kzalloc_obj(*soc_dev_attr);
 	if (!soc_dev_attr) {
 		ret = -ENOMEM;
-		goto out;
+		goto out_free_info;
 	}
 
 	soc_dev_attr->family = kasprintf(GFP_KERNEL, "%x",
-					 family_id >> 28 ?
-					 family_id >> 16 : family_id >> 8);
+					 soc_info->family_id >> 28 ?
+					 soc_info->family_id >> 16 : soc_info->family_id >> 8);
 	soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%x",
-					 product_id >> 28 ?
-					 product_id >> 16 : product_id >> 8);
+					 soc_info->product_id >> 28 ?
+					 soc_info->product_id >> 16 : soc_info->product_id >> 8);
 	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%c%d",
-					 ((product_id & 0xf0) >> 4) + 'A',
-					   product_id & 0xf);
+					 ((soc_info->product_id & 0xf0) >> 4) + 'A',
+					   soc_info->product_id & 0xf);
 
 	soc_dev = soc_device_register(soc_dev_attr);
 	if (IS_ERR(soc_dev)) {
-		kfree(soc_dev_attr->family);
-		kfree(soc_dev_attr->soc_id);
-		kfree(soc_dev_attr->revision);
-		kfree(soc_dev_attr);
-		ret = -ENOMEM;
+		ret = PTR_ERR(soc_dev);
+		goto out_free_attr;
 	}
-out:
+
+	iounmap(sun_top_ctrl_base);
+	of_node_put(sun_top_ctrl);
+	return 0;
+
+out_free_attr:
+	kfree(soc_dev_attr->revision);
+	kfree(soc_dev_attr->soc_id);
+	kfree(soc_dev_attr->family);
+	kfree(soc_dev_attr);
+out_free_info:
+	kfree(soc_info);
+	soc_info = NULL;
+out_unmap:
+	iounmap(sun_top_ctrl_base);
+out_put_node:
 	of_node_put(sun_top_ctrl);
 	return ret;
 }
-arch_initcall(brcmstb_soc_device_init);
+early_initcall(brcmstb_soc_device_init);
-- 
2.34.1



^ permalink raw reply related

* Re: [PATCH v3 3/9] media: rockchip: rkcif: add support for rk3588 vicap mipi capture
From: Mehdi Djait @ 2026-03-25 17:38 UTC (permalink / raw)
  To: michael.riesch
  Cc: Laurent Pinchart, Mauro Carvalho Chehab, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner, Kever Yang,
	Jagan Teki,
	Кузнецов Михаил,
	Charalampos Mitrodimas, Sebastian Reichel, Nicolas Dufresne,
	Collabora Kernel Team, Sakari Ailus, linux-media, devicetree,
	linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <20250430-rk3588-vicap-v3-3-e38e428868cc@collabora.com>

Hi Michael,

Thank you for the patch!

On Wed, Mar 25, 2026 at 12:51:08PM +0100, Michael Riesch via B4 Relay wrote:
> From: Michael Riesch <michael.riesch@collabora.com>
> 
> The RK3588 Video Capture (VICAP) unit features a Digital Video Port
> (DVP) and six MIPI CSI-2 capture interfaces. Add initial support
> for this variant to the rkcif driver and enable the MIPI CSI-2
> capture interfaces.
> 

Reviewed-by: Mehdi Djait <mehdi.djait@linux.intel.com>

> Signed-off-by: Michael Riesch <michael.riesch@collabora.com>
> ---
>  .../platform/rockchip/rkcif/rkcif-capture-mipi.c   | 141 +++++++++++++++++++++
>  .../platform/rockchip/rkcif/rkcif-capture-mipi.h   |   1 +
>  .../media/platform/rockchip/rkcif/rkcif-common.h   |   2 +-
>  drivers/media/platform/rockchip/rkcif/rkcif-dev.c  |  18 +++
>  4 files changed, 161 insertions(+), 1 deletion(-)

--
Kind Regards
Mehdi Djait


^ permalink raw reply

* Re: [PATCH v1 2/3] arm64: mm: Handle invalid large leaf mappings correctly
From: Ryan Roberts @ 2026-03-25 17:37 UTC (permalink / raw)
  To: Yang Shi, Catalin Marinas, Will Deacon, David Hildenbrand (Arm),
	Dev Jain, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <401073fd-3438-419d-8287-35eea61919b0@os.amperecomputing.com>

On 24/03/2026 18:20, Yang Shi wrote:
> 
> 
> On 3/23/26 6:03 AM, Ryan Roberts wrote:
>> It has been possible for a long time to mark ptes in the linear map as
>> invalid. This is done for secretmem, kfence, realm dma memory un/share,
>> and others, by simply clearing the PTE_VALID bit. But until commit
>> a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") large leaf mappings were never made invalid in this way.
>>
>> It turns out various parts of the code base are not equipped to handle
>> invalid large leaf mappings (in the way they are currently encoded) and
>> I've observed a kernel panic while booting a realm guest on a
>> BBML2_NOABORT system as a result:
>>
>> [   15.432706] software IO TLB: Memory encryption is active and system is
>> using DMA bounce buffers
>> [   15.476896] Unable to handle kernel paging request at virtual address
>> ffff000019600000
>> [   15.513762] Mem abort info:
>> [   15.527245]   ESR = 0x0000000096000046
>> [   15.548553]   EC = 0x25: DABT (current EL), IL = 32 bits
>> [   15.572146]   SET = 0, FnV = 0
>> [   15.592141]   EA = 0, S1PTW = 0
>> [   15.612694]   FSC = 0x06: level 2 translation fault
>> [   15.640644] Data abort info:
>> [   15.661983]   ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
>> [   15.694875]   CM = 0, WnR = 1, TnD = 0, TagAccess = 0
>> [   15.723740]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>> [   15.755776] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081f3f000
>> [   15.800410] [ffff000019600000] pgd=0000000000000000, p4d=180000009ffff403,
>> pud=180000009fffe403, pmd=00e8000199600704
>> [   15.855046] Internal error: Oops: 0000000096000046 [#1]  SMP
>> [   15.886394] Modules linked in:
>> [   15.900029] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-rc4-
>> dirty #4 PREEMPT
>> [   15.935258] Hardware name: linux,dummy-virt (DT)
>> [   15.955612] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>> [   15.986009] pc : __pi_memcpy_generic+0x128/0x22c
>> [   16.006163] lr : swiotlb_bounce+0xf4/0x158
>> [   16.024145] sp : ffff80008000b8f0
>> [   16.038896] x29: ffff80008000b8f0 x28: 0000000000000000 x27: 0000000000000000
>> [   16.069953] x26: ffffb3976d261ba8 x25: 0000000000000000 x24: ffff000019600000
>> [   16.100876] x23: 0000000000000001 x22: ffff0000043430d0 x21: 0000000000007ff0
>> [   16.131946] x20: 0000000084570010 x19: 0000000000000000 x18: ffff00001ffe3fcc
>> [   16.163073] x17: 0000000000000000 x16: 00000000003fffff x15: 646e612065766974
>> [   16.194131] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
>> [   16.225059] x11: 0000000000000000 x10: 0000000000000010 x9 : 0000000000000018
>> [   16.256113] x8 : 0000000000000018 x7 : 0000000000000000 x6 : 0000000000000000
>> [   16.287203] x5 : ffff000019607ff0 x4 : ffff000004578000 x3 : ffff000019600000
>> [   16.318145] x2 : 0000000000007ff0 x1 : ffff000004570010 x0 : ffff000019600000
>> [   16.349071] Call trace:
>> [   16.360143]  __pi_memcpy_generic+0x128/0x22c (P)
>> [   16.380310]  swiotlb_tbl_map_single+0x154/0x2b4
>> [   16.400282]  swiotlb_map+0x5c/0x228
>> [   16.415984]  dma_map_phys+0x244/0x2b8
>> [   16.432199]  dma_map_page_attrs+0x44/0x58
>> [   16.449782]  virtqueue_map_page_attrs+0x38/0x44
>> [   16.469596]  virtqueue_map_single_attrs+0xc0/0x130
>> [   16.490509]  virtnet_rq_alloc.isra.0+0xa4/0x1fc
>> [   16.510355]  try_fill_recv+0x2a4/0x584
>> [   16.526989]  virtnet_open+0xd4/0x238
>> [   16.542775]  __dev_open+0x110/0x24c
>> [   16.558280]  __dev_change_flags+0x194/0x20c
>> [   16.576879]  netif_change_flags+0x24/0x6c
>> [   16.594489]  dev_change_flags+0x48/0x7c
>> [   16.611462]  ip_auto_config+0x258/0x1114
>> [   16.628727]  do_one_initcall+0x80/0x1c8
>> [   16.645590]  kernel_init_freeable+0x208/0x2f0
>> [   16.664917]  kernel_init+0x24/0x1e0
>> [   16.680295]  ret_from_fork+0x10/0x20
>> [   16.696369] Code: 927cec03 cb0e0021 8b0e0042 a9411c26 (a900340c)
>> [   16.723106] ---[ end trace 0000000000000000 ]---
>> [   16.752866] Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b
>> [   16.792556] Kernel Offset: 0x3396ea200000 from 0xffff800080000000
>> [   16.818966] PHYS_OFFSET: 0xfff1000080000000
>> [   16.837237] CPU features: 0x0000000,00060005,13e38581,957e772f
>> [   16.862904] Memory Limit: none
>> [   16.876526] ---[ end Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b ]---
>>
>> This panic occurs because the swiotlb memory was previously shared to
>> the host (__set_memory_enc_dec()), which involves transitioning the
>> (large) leaf mappings to invalid, sharing to the host, then marking the
>> mappings valid again. But pageattr_p[mu]d_entry() would only update the
>> entry if it is a section mapping, since otherwise it concluded it must
>> be a table entry so shouldn't be modified. But p[mu]d_sect() only
>> returns true if the entry is valid. So the result was that the large
>> leaf entry was made invalid in the first pass then ignored in the second
>> pass. It remains invalid until the above code tries to access it and
>> blows up.
> 
> Good catch. I recall I met this problem when I worked on a very early PoC of
> large block mapping patch. It took a total different approach than
> BBML2_NOABORT. I didn't run into that problem when I implemented BBML2_NOABORT
> because nobody actually changed valid/invalid attribute on large block mapping
> granule so I forgot it. But I definitely missed realm usecase.
> 
>>
>> The simple fix would be to update pageattr_pmd_entry() to use
>> !pmd_table() instead of pmd_sect(). That would solve this problem.
> 
> Yes, I agree.
> 
>>
>> But the ptdump code also suffers from a similar issue. It checks
>> pmd_leaf() and doesn't call into the arch-specific note_page() machinery
>> if it returns false. As a result of this, ptdump wasn't even able to
>> show the invalid large leaf mappings; it looked like they were valid
>> which made this super fun to debug. the ptdump code is core-mm and
>> pmd_table() is arm64-specific so we can't use the same trick to solve
>> that.
> 
> I don't quite get why we need to show invalid mappings in ptdump? IIUC ptdump is
> not supposed to show invalid mappings even though they are transient.

Let's say we have 8M of PMD mappings, then we want to mark 2M in the middle of
that as invalid. Prior to my fix, ptdump would show the full 8M as still being
valid after making the middle 2M invalid. This happened because the note_page()
call for the 2M invalid part was suppressed, but there was also no ptdump_hole()
call since the PMD entry is not none. After my fix, we call note_page() for the
non-none but invalid pmd and now the "F" is correctly displayed for that portion.

Thanks,
Ryan



> 
> Thanks,
> Yang
> 
> 
>>
>> But we already support the concept of "present-invalid" for user space
>> entries. And even better, pmd_leaf() will return true for a leaf mapping
>> that is marked present-invalid. So let's just use that encoding for
>> present-invalid kernel mappings too. Then we can use pmd_leaf() where we
>> previously used pmd_sect() and everything is magically fixed.
>>
>> Additionally, from inspection kernel_page_present() was broken in a
>> similar way, so I'm also updating that to use pmd_leaf().
>>
>> I haven't spotted any other issues of this shape but plan to do a follow
>> up patch to remove pmd_sect() and pud_sect() in favour of the more
>> sophisticated pmd_leaf()/pud_leaf() which are core-mm APIs and will
>> simplify arm64 code a bit.
>>
>> Fixes: a166563e7ec37 ("arm64: mm: support large block mapping when rodata=full")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Ryan Roberts <ryan.roberts@arm.com>
>> ---
>>   arch/arm64/mm/pageattr.c | 50 ++++++++++++++++++++++------------------
>>   1 file changed, 28 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
>> index 358d1dc9a576f..87dfe4c82fa92 100644
>> --- a/arch/arm64/mm/pageattr.c
>> +++ b/arch/arm64/mm/pageattr.c
>> @@ -25,6 +25,11 @@ static ptdesc_t set_pageattr_masks(ptdesc_t val, struct
>> mm_walk *walk)
>>   {
>>       struct page_change_data *masks = walk->private;
>>   +    /*
>> +     * Some users clear and set bits which alias eachother (e.g. PTE_NG and
>> +     * PTE_PRESENT_INVALID). It is therefore important that we always clear
>> +     * first then set.
>> +     */
>>       val &= ~(pgprot_val(masks->clear_mask));
>>       val |= (pgprot_val(masks->set_mask));
>>   @@ -36,7 +41,7 @@ static int pageattr_pud_entry(pud_t *pud, unsigned long addr,
>>   {
>>       pud_t val = pudp_get(pud);
>>   -    if (pud_sect(val)) {
>> +    if (pud_leaf(val)) {
>>           if (WARN_ON_ONCE((next - addr) != PUD_SIZE))
>>               return -EINVAL;
>>           val = __pud(set_pageattr_masks(pud_val(val), walk));
>> @@ -52,7 +57,7 @@ static int pageattr_pmd_entry(pmd_t *pmd, unsigned long addr,
>>   {
>>       pmd_t val = pmdp_get(pmd);
>>   -    if (pmd_sect(val)) {
>> +    if (pmd_leaf(val)) {
>>           if (WARN_ON_ONCE((next - addr) != PMD_SIZE))
>>               return -EINVAL;
>>           val = __pmd(set_pageattr_masks(pmd_val(val), walk));
>> @@ -132,11 +137,12 @@ static int __change_memory_common(unsigned long start,
>> unsigned long size,
>>       ret = update_range_prot(start, size, set_mask, clear_mask);
>>         /*
>> -     * If the memory is being made valid without changing any other bits
>> -     * then a TLBI isn't required as a non-valid entry cannot be cached in
>> -     * the TLB.
>> +     * If the memory is being switched from present-invalid to valid without
>> +     * changing any other bits then a TLBI isn't required as a non-valid
>> +     * entry cannot be cached in the TLB.
>>        */
>> -    if (pgprot_val(set_mask) != PTE_VALID || pgprot_val(clear_mask))
>> +    if (pgprot_val(set_mask) != (PTE_MAYBE_NG | PTE_VALID) ||
>> +        pgprot_val(clear_mask) != PTE_PRESENT_INVALID)
>>           flush_tlb_kernel_range(start, start + size);
>>       return ret;
>>   }
>> @@ -237,18 +243,18 @@ int set_memory_valid(unsigned long addr, int numpages,
>> int enable)
>>   {
>>       if (enable)
>>           return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                    __pgprot(PTE_VALID),
>> -                    __pgprot(0));
>> +                    __pgprot(PTE_MAYBE_NG | PTE_VALID),
>> +                    __pgprot(PTE_PRESENT_INVALID));
>>       else
>>           return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                    __pgprot(0),
>> -                    __pgprot(PTE_VALID));
>> +                    __pgprot(PTE_PRESENT_INVALID),
>> +                    __pgprot(PTE_MAYBE_NG | PTE_VALID));
>>   }
>>     int set_direct_map_invalid_noflush(struct page *page)
>>   {
>> -    pgprot_t clear_mask = __pgprot(PTE_VALID);
>> -    pgprot_t set_mask = __pgprot(0);
>> +    pgprot_t clear_mask = __pgprot(PTE_MAYBE_NG | PTE_VALID);
>> +    pgprot_t set_mask = __pgprot(PTE_PRESENT_INVALID);
>>         if (!can_set_direct_map())
>>           return 0;
>> @@ -259,8 +265,8 @@ int set_direct_map_invalid_noflush(struct page *page)
>>     int set_direct_map_default_noflush(struct page *page)
>>   {
>> -    pgprot_t set_mask = __pgprot(PTE_VALID | PTE_WRITE);
>> -    pgprot_t clear_mask = __pgprot(PTE_RDONLY);
>> +    pgprot_t set_mask = __pgprot(PTE_MAYBE_NG | PTE_VALID | PTE_WRITE);
>> +    pgprot_t clear_mask = __pgprot(PTE_PRESENT_INVALID | PTE_RDONLY);
>>         if (!can_set_direct_map())
>>           return 0;
>> @@ -296,8 +302,8 @@ static int __set_memory_enc_dec(unsigned long addr,
>>        * entries or Synchronous External Aborts caused by RIPAS_EMPTY
>>        */
>>       ret = __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                     __pgprot(set_prot),
>> -                     __pgprot(clear_prot | PTE_VALID));
>> +                     __pgprot(set_prot | PTE_PRESENT_INVALID),
>> +                     __pgprot(clear_prot | PTE_MAYBE_NG | PTE_VALID));
>>         if (ret)
>>           return ret;
>> @@ -311,8 +317,8 @@ static int __set_memory_enc_dec(unsigned long addr,
>>           return ret;
>>         return __change_memory_common(addr, PAGE_SIZE * numpages,
>> -                      __pgprot(PTE_VALID),
>> -                      __pgprot(0));
>> +                      __pgprot(PTE_MAYBE_NG | PTE_VALID),
>> +                      __pgprot(PTE_PRESENT_INVALID));
>>   }
>>     static int realm_set_memory_encrypted(unsigned long addr, int numpages)
>> @@ -404,15 +410,15 @@ bool kernel_page_present(struct page *page)
>>       pud = READ_ONCE(*pudp);
>>       if (pud_none(pud))
>>           return false;
>> -    if (pud_sect(pud))
>> -        return true;
>> +    if (pud_leaf(pud))
>> +        return pud_valid(pud);
>>         pmdp = pmd_offset(pudp, addr);
>>       pmd = READ_ONCE(*pmdp);
>>       if (pmd_none(pmd))
>>           return false;
>> -    if (pmd_sect(pmd))
>> -        return true;
>> +    if (pmd_leaf(pmd))
>> +        return pmd_valid(pmd);
>>         ptep = pte_offset_kernel(pmdp, addr);
>>       return pte_valid(__ptep_get(ptep));
> 



^ permalink raw reply

* Re: [PATCH v3 3/7] pinctrl: pinctrl-generic: add __pinctrl_generic_pins_function_dt_node_to_map()
From: Conor Dooley @ 2026-03-25 17:34 UTC (permalink / raw)
  To: Frank Li
  Cc: Linus Walleij, Peter Rosin, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Rafał Miłecki, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-kernel, linux-gpio,
	devicetree, imx, linux-arm-kernel, Haibo Chen
In-Reply-To: <acP6oFsaD8PddWjg@lizhi-Precision-Tower-5810>

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

On Wed, Mar 25, 2026 at 11:09:20AM -0400, Frank Li wrote:
> On Wed, Mar 25, 2026 at 10:33:05AM +0000, Conor Dooley wrote:
> > On Tue, Mar 24, 2026 at 04:16:10PM -0400, Frank Li wrote:
> > > On Fri, Mar 20, 2026 at 09:54:45AM -0400, Frank Li wrote:
> > > > On Fri, Mar 20, 2026 at 02:27:21PM +0100, Linus Walleij wrote:
> > > > > On Thu, Mar 19, 2026 at 12:04 AM Frank Li <Frank.li@nxp.com> wrote:
> > > > > > On Mon, Mar 16, 2026 at 10:37:28AM +0100, Linus Walleij wrote:
> > > > >
> > > > > > > That said: in this case you're just adding a parameter, just add
> > > > > > > the parameter and change all of the in-tree users to pass false
> > > > > > > or whatever you need, these is just one (1) in-tree user anyway.
> > > > > >
> > > > > > pinctrl_generic_pins_function_dt_node_to_map() directly feed to
> > > > > > .dt_node_to_map() callback, add parameter will impact too much.
> > > > >
> > > > > Why do you say that. It already has many parameters, one more
> > > > > or less doesn't matter. It's not like this call is performance-critical.
> > > > > Just change the users.
> > > >
> > > > In only user drivers/pinctrl/microchip/pinctrl-mpfs-mssio.c,
> > > > 	.dt_node_to_map = pinctrl_generic_pins_function_dt_node_to_map;
> > > >
> > > > pinctrl_generic_pins_function_dt_node_to_map() need match .dt_node_to_map()'s
> > > > declear.
> > > >
> > > > So it can't direct add two parameters in pinctrl_generic_pins_function_dt_node_to_map()
> > > > Need simple wrap function, which other in pinctrl-mpfs-mssio.c or in
> > > > pinconf.h.
> > > >
> > > > If add two parameter in .dt_node_to_map(), need change all functions, which
> > > > .dt_node_to_map = xxx_to_map(). and OF core part.
> > >
> > > Linus Walleij:
> > > 	Is my explain clear enough? I am preparing respin it?
> > >
> > > 	is okay use wrap function
> > > 	pinctrl_generic_pins_function_dt_node_to_map_ext()?
> >
> > I don't understand this patch. The function is called
> > pinctrl_generic_pins_function_dt_node_to_map(). You have no pins.
> > You're adding a parameter to make a function with *pins* in its name not
> > use pins. The new function doesn't use pins but has pins in the name.
> > At the very least function names should not be misleading.
> >
> > I was going to suggest pulling out the relevant portions and creating
> > some helpers that could be used by multiple different-but-similar
> > functions, but I don't actually even think that there's much in common.
> > Most damningly I think, you don't actually read either the functions or
> > pins properties at all and neither are permitted by your binding.
> > So turns out you use neither pins or functions...
> >
> > You don't actually have any of these properties which runs counter to the
> > goal of the function, which is parsing. With this in mind, it feels to me
> > like you're trying way too hard to make use of a generic function when the
> > right thing to do is probably just have an entirely custom function.
> > Maybe that's a custom implementation in your driver, or a new function
> > here, but I think writing that will highlight just how little of the
> > code would be shared between the existing function and what your
> > use-case needs: no pin configuration stuff, no reading of the devicetree
> > other than the node names and no dealing with the label pointing to the
> > "wrong" place.
> >
> > I recently bought a spacemit k1 board to go and write a sister function
> > to pinctrl_generic_pins_function_dt_node_to_map() that deals with pins
> > and groups (because that's a pretty common pattern).
> > I would be calling that pinctrl_generic_pinmux_dt_node_to_map(),
> > because it that's the property it deals with. I have honestly got no
> > idea what to call one for this situation since you don't have any of the
> > properties in pinmux-node.yaml. Maybe that's a sign.
> 
> At v2, I implemented customize dt_node_to_map(), Linus Walleij think it is
> too similar with pinctrl_generic_pins_function_dt_node_to_map(), so ask me
> to enhanance and reuse pinctrl_generic_pins_function_dt_node_to_map().

Sure, and he's right that there's a lot similar. Everything you want to
do, other than looking at the mux state, is something that
pinctrl_generic_pins_function_dt_node_to_map() does. But bastardising
a function that's explicitly about reading pins and functions properties
to do things that have _neither_ is not a good implementation of that
review feedback.

If you're going to make something generic, the right level to hook in
IMO is at the pinctrl_generic_pins_function_dt_subnode_to_map() level,
I already know that 95% of the code in that function is identical to
what will be used for the spacemit k1 that uses the pinmux property
and changing its API is a lot easier than changing the API of something
that is written to match the dt_node_to_map callback.
You don't even benefit from the extra functionality that
pinctrl_generic_pins_function_dt_node_to_map() provides, because you
don't have ambiguity about where the phandle you're parsing from points.
In your case, it has to be the group node.

pinctrl_generic_pins_function_dt_subnode_to_map() could probably be
split into two parts, one that does the dt parsing portion and a second
portion that does the mapping to kernel data structures. The first
portion of that is the for loop. The second portion is everything after
the for loop and the bit that names the groups. IOW, do something like
what I am pasting here, and you create your own function that wraps
pinctrl_generic_to_map() in the way you want. I personally think this is
more tasteful than what you've done, and more importantly I am pretty
sure that this is what's needed to be able to maximise code reuse for
the devices that use pinmux. I didn't compile this or anything, it's
just speculative.

diff --git a/drivers/pinctrl/pinctrl-generic.c b/drivers/pinctrl/pinctrl-generic.c
index efb39c6a67033..7f02af6d9f3e4 100644
--- a/drivers/pinctrl/pinctrl-generic.c
+++ b/drivers/pinctrl/pinctrl-generic.c
@@ -17,56 +17,30 @@
 #include "pinctrl-utils.h"
 #include "pinmux.h"
 
-static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
-							   struct device_node *parent,
-							   struct device_node *np,
-							   struct pinctrl_map **maps,
-							   unsigned int *num_maps,
-							   unsigned int *num_reserved_maps,
-							   const char **group_names,
-							   unsigned int ngroups)
+static int pinctrl_generic_to_map(struct pinctrl_dev *pctldev,
+				  struct device_node *parent,
+				  struct device_node *np,
+				  struct pinctrl_map **maps,
+				  unsigned int *num_maps,
+				  unsigned int *num_reserved_maps,
+				  const char **group_names,
+				  unsigned int ngroups,
+				  const char **functions,
+				  unsigned int *pins,
+				  void *function_data)
 {
 	struct device *dev = pctldev->dev;
-	const char **functions;
 	const char *group_name;
 	unsigned long *configs;
-	unsigned int num_configs, pin, *pins;
+	unsigned int num_configs;
 	int npins, ret, reserve = 1;
 
-	npins = of_property_count_u32_elems(np, "pins");
-
-	if (npins < 1) {
-		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
-			parent, np, npins);
-		return npins;
-	}
-
 	group_name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn.%pOFn", parent, np);
 	if (!group_name)
 		return -ENOMEM;
 
 	group_names[ngroups] = group_name;
 
-	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
-	if (!pins)
-		return -ENOMEM;
-
-	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
-	if (!functions)
-		return -ENOMEM;
-
-	for (int i = 0; i < npins; i++) {
-		ret = of_property_read_u32_index(np, "pins", i, &pin);
-		if (ret)
-			return ret;
-
-		pins[i] = pin;
-
-		ret = of_property_read_string(np, "function", &functions[i]);
-		if (ret)
-			return ret;
-	}
-
 	ret = pinctrl_utils_reserve_map(pctldev, maps, num_reserved_maps, num_maps, reserve);
 	if (ret)
 		return ret;
@@ -101,6 +75,52 @@ static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *p
 		return ret;
 
 	return 0;
+}
+
+static int pinctrl_generic_pins_function_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+							   struct device_node *parent,
+							   struct device_node *np,
+							   struct pinctrl_map **maps,
+							   unsigned int *num_maps,
+							   unsigned int *num_reserved_maps,
+							   const char **group_names,
+							   unsigned int ngroups)
+{
+	struct device *dev = pctldev->dev;
+	const char **functions;
+	unsigned int pin, *pins;
+	int npins, ret;
+
+	npins = of_property_count_u32_elems(np, "pins");
+
+	if (npins < 1) {
+		dev_err(dev, "invalid pinctrl group %pOFn.%pOFn %d\n",
+			parent, np, npins);
+		return npins;
+	}
+
+	pins = devm_kcalloc(dev, npins, sizeof(*pins), GFP_KERNEL);
+	if (!pins)
+		return -ENOMEM;
+
+	functions = devm_kcalloc(dev, npins, sizeof(*functions), GFP_KERNEL);
+	if (!functions)
+		return -ENOMEM;
+
+	for (int i = 0; i < npins; i++) {
+		ret = of_property_read_u32_index(np, "pins", i, &pin);
+		if (ret)
+			return ret;
+
+		pins[i] = pin;
+
+		ret = of_property_read_string(np, "function", &functions[i]);
+		if (ret)
+			return ret;
+	}
+	return pinctrl_generic_to_map(pctldev, parent, np, maps, num_maps,
+				  num_reserved_maps, group_names, ngroups,
+				  functions, pins, NULL);
 };
 
 /*



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

^ permalink raw reply related

* Re: [PATCH v1 0/2] i2c: imx: fix i2c issues when reading messages
From: Andi Shyti @ 2026-03-25 17:32 UTC (permalink / raw)
  To: Stefan Eichenberger
  Cc: o.rempel, kernel, Frank.Li, s.hauer, festevam,
	stefan.eichenberger, francesco.dolcini, linux-i2c, imx,
	linux-arm-kernel, linux-kernel
In-Reply-To: <20260218150940.131354-1-eichest@gmail.com>

Hi Stefan,

> Stefan Eichenberger (2):
>   i2c: imx: fix i2c issue when reading multiple messages
>   i2c: imx: ensure no clock is generated after last read

merged to i2c/i2c-host-fixes.

Thanks,
Andi


^ permalink raw reply

* Re: [PATCH v1 2/3] arm64: mm: Handle invalid large leaf mappings correctly
From: Ryan Roberts @ 2026-03-25 17:31 UTC (permalink / raw)
  To: Jinjiang Tu, Catalin Marinas, Will Deacon,
	David Hildenbrand (Arm), Dev Jain, Yang Shi, Suzuki K Poulose,
	Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <a7fa6fd9-79b2-4e46-8ee4-fde9d5853100@huawei.com>

On 24/03/2026 02:30, Jinjiang Tu wrote:
> 
> 在 2026/3/23 21:03, Ryan Roberts 写道:
>> It has been possible for a long time to mark ptes in the linear map as
>> invalid. This is done for secretmem, kfence, realm dma memory un/share,
>> and others, by simply clearing the PTE_VALID bit. But until commit
>> a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") large leaf mappings were never made invalid in this way.
>>
>> It turns out various parts of the code base are not equipped to handle
>> invalid large leaf mappings (in the way they are currently encoded) and
>> I've observed a kernel panic while booting a realm guest on a
>> BBML2_NOABORT system as a result:
>>
>> [   15.432706] software IO TLB: Memory encryption is active and system is
>> using DMA bounce buffers
>> [   15.476896] Unable to handle kernel paging request at virtual address
>> ffff000019600000
>> [   15.513762] Mem abort info:
>> [   15.527245]   ESR = 0x0000000096000046
>> [   15.548553]   EC = 0x25: DABT (current EL), IL = 32 bits
>> [   15.572146]   SET = 0, FnV = 0
>> [   15.592141]   EA = 0, S1PTW = 0
>> [   15.612694]   FSC = 0x06: level 2 translation fault
>> [   15.640644] Data abort info:
>> [   15.661983]   ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
>> [   15.694875]   CM = 0, WnR = 1, TnD = 0, TagAccess = 0
>> [   15.723740]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
>> [   15.755776] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000081f3f000
>> [   15.800410] [ffff000019600000] pgd=0000000000000000, p4d=180000009ffff403,
>> pud=180000009fffe403, pmd=00e8000199600704
>> [   15.855046] Internal error: Oops: 0000000096000046 [#1]  SMP
>> [   15.886394] Modules linked in:
>> [   15.900029] CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 7.0.0-rc4-
>> dirty #4 PREEMPT
>> [   15.935258] Hardware name: linux,dummy-virt (DT)
>> [   15.955612] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
>> [   15.986009] pc : __pi_memcpy_generic+0x128/0x22c
>> [   16.006163] lr : swiotlb_bounce+0xf4/0x158
>> [   16.024145] sp : ffff80008000b8f0
>> [   16.038896] x29: ffff80008000b8f0 x28: 0000000000000000 x27: 0000000000000000
>> [   16.069953] x26: ffffb3976d261ba8 x25: 0000000000000000 x24: ffff000019600000
>> [   16.100876] x23: 0000000000000001 x22: ffff0000043430d0 x21: 0000000000007ff0
>> [   16.131946] x20: 0000000084570010 x19: 0000000000000000 x18: ffff00001ffe3fcc
>> [   16.163073] x17: 0000000000000000 x16: 00000000003fffff x15: 646e612065766974
>> [   16.194131] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
>> [   16.225059] x11: 0000000000000000 x10: 0000000000000010 x9 : 0000000000000018
>> [   16.256113] x8 : 0000000000000018 x7 : 0000000000000000 x6 : 0000000000000000
>> [   16.287203] x5 : ffff000019607ff0 x4 : ffff000004578000 x3 : ffff000019600000
>> [   16.318145] x2 : 0000000000007ff0 x1 : ffff000004570010 x0 : ffff000019600000
>> [   16.349071] Call trace:
>> [   16.360143]  __pi_memcpy_generic+0x128/0x22c (P)
>> [   16.380310]  swiotlb_tbl_map_single+0x154/0x2b4
>> [   16.400282]  swiotlb_map+0x5c/0x228
>> [   16.415984]  dma_map_phys+0x244/0x2b8
>> [   16.432199]  dma_map_page_attrs+0x44/0x58
>> [   16.449782]  virtqueue_map_page_attrs+0x38/0x44
>> [   16.469596]  virtqueue_map_single_attrs+0xc0/0x130
>> [   16.490509]  virtnet_rq_alloc.isra.0+0xa4/0x1fc
>> [   16.510355]  try_fill_recv+0x2a4/0x584
>> [   16.526989]  virtnet_open+0xd4/0x238
>> [   16.542775]  __dev_open+0x110/0x24c
>> [   16.558280]  __dev_change_flags+0x194/0x20c
>> [   16.576879]  netif_change_flags+0x24/0x6c
>> [   16.594489]  dev_change_flags+0x48/0x7c
>> [   16.611462]  ip_auto_config+0x258/0x1114
>> [   16.628727]  do_one_initcall+0x80/0x1c8
>> [   16.645590]  kernel_init_freeable+0x208/0x2f0
>> [   16.664917]  kernel_init+0x24/0x1e0
>> [   16.680295]  ret_from_fork+0x10/0x20
>> [   16.696369] Code: 927cec03 cb0e0021 8b0e0042 a9411c26 (a900340c)
>> [   16.723106] ---[ end trace 0000000000000000 ]---
>> [   16.752866] Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b
>> [   16.792556] Kernel Offset: 0x3396ea200000 from 0xffff800080000000
>> [   16.818966] PHYS_OFFSET: 0xfff1000080000000
>> [   16.837237] CPU features: 0x0000000,00060005,13e38581,957e772f
>> [   16.862904] Memory Limit: none
>> [   16.876526] ---[ end Kernel panic - not syncing: Attempted to kill init!
>> exitcode=0x0000000b ]---
>>
>> This panic occurs because the swiotlb memory was previously shared to
>> the host (__set_memory_enc_dec()), which involves transitioning the
>> (large) leaf mappings to invalid, sharing to the host, then marking the
>> mappings valid again. But pageattr_p[mu]d_entry() would only update the
>> entry if it is a section mapping, since otherwise it concluded it must
>> be a table entry so shouldn't be modified. But p[mu]d_sect() only
>> returns true if the entry is valid. So the result was that the large
> 
> Maybe I missed something, pmd_sect() only checks PMD_TYPE_SECT, doesn't check
> PTE_VALID?
> Why it only returns true if the entry is valid?

PTE_VALID is bit 0.

#define PMD_TYPE_MASK		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_TABLE		(_AT(pmdval_t, 3) << 0)
#define PMD_TYPE_SECT		(_AT(pmdval_t, 1) << 0)

So PMD_TYPE_TABLE and PMD_TYPE_SECT are both implicitly checking that PTE_VALID
is set.

> 
> #define pmd_sect(pmd)        ((pmd_val(pmd) & PMD_TYPE_MASK) == \
>                  PMD_TYPE_SECT)
> 

Thanks,
Ryan



^ permalink raw reply

* Re: [PATCH v1 1/3] arm64: mm: Fix rodata=full block mapping support for realm guests
From: Ryan Roberts @ 2026-03-25 17:29 UTC (permalink / raw)
  To: Yang Shi, Catalin Marinas, Will Deacon, David Hildenbrand (Arm),
	Dev Jain, Suzuki K Poulose, Jinjiang Tu, Kevin Brodsky
  Cc: linux-arm-kernel, linux-kernel, stable
In-Reply-To: <a3766dfc-06ed-4cdc-9c55-0dcc3638746e@os.amperecomputing.com>

On 23/03/2026 21:34, Yang Shi wrote:
> 
> 
> On 3/23/26 6:03 AM, Ryan Roberts wrote:
>> Commit a166563e7ec37 ("arm64: mm: support large block mapping when
>> rodata=full") enabled the linear map to be mapped by block/cont while
>> still allowing granular permission changes on BBML2_NOABORT systems by
>> lazily splitting the live mappings. This mechanism was intended to be
>> usable by realm guests since they need to dynamically share dma buffers
>> with the host by "decrypting" them - which for Arm CCA, means marking
>> them as shared in the page tables.
>>
>> However, it turns out that the mechanism was failing for realm guests
>> because realms need to share their dma buffers (via
>> __set_memory_enc_dec()) much earlier during boot than
>> split_kernel_leaf_mapping() was able to handle. The report linked below
>> showed that GIC's ITS was one such user. But during the investigation I
>> found other callsites that could not meet the
>> split_kernel_leaf_mapping() constraints.
>>
>> The problem is that we block map the linear map based on the boot CPU
>> supporting BBML2_NOABORT, then check that all the other CPUs support it
>> too when finalizing the caps. If they don't, then we stop_machine() and
>> split to ptes. For safety, split_kernel_leaf_mapping() previously
>> wouldn't permit splitting until after the caps were finalized. That
>> ensured that if any secondary cpus were running that didn't support
>> BBML2_NOABORT, we wouldn't risk breaking them.
>>
>> I've fix this problem by reducing the black-out window where we refuse
>> to split; there are now 2 windows. The first is from T0 until the page
>> allocator is inititialized. Splitting allocates memory for the page
>> allocator so it must be in use. The second covers the period between
>> starting to online the secondary cpus until the system caps are
>> finalized (this is a very small window).
>>
>> All of the problematic callers are calling __set_memory_enc_dec() before
>> the secondary cpus come online, so this solves the problem. However, one
>> of these callers, swiotlb_update_mem_attributes(), was trying to split
>> before the page allocator was initialized. So I have moved this call
>> from arch_mm_preinit() to mem_init(), which solves the ordering issue.
>>
>> I've added warnings and return an error if any attempt is made to split
>> in the black-out windows.
>>
>> Note there are other issues which prevent booting all the way to user
>> space, which will be fixed in subsequent patches.
> 
> Hi Ryan,
> 
> Thanks for putting everything to together to have the patches so quickly. It
> basically looks good to me. However, I'm thinking about whether we should have
> split_kernel_leaf_mapping() call for different memory allocators in different
> stages. If buddy has been initialized, it can call page allocator, otherwise,
> for example, in early boot stage, it can call memblock allocator. So
> split_kernel_leaf_mapping() should be able to be called anytime and we don't
> have to rely on the boot order of subsystems.

I considered that, but ultimately we would just be adding dead code. I've added
a warning that will catch this usage. So I'd prefer to leave it as is for now
and only add this functionality if we identify a need.

Thanks,
Ryan


> 
> Thanks,
> Yang
> 


^ permalink raw reply

* Re: [PATCH v5 09/10] clk: realtek: Add RTD1625-CRT clock controller driver
From: Philipp Zabel @ 2026-03-25 17:24 UTC (permalink / raw)
  To: Yu-Chun Lin, mturquette, sboyd, robh, krzk+dt, conor+dt, cylee12,
	afaerber, jyanchou
  Cc: devicetree, linux-clk, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, james.tai, cy.huang, stanley_chang
In-Reply-To: <20260324025332.3416977-10-eleanor.lin@realtek.com>

On Di, 2026-03-24 at 10:53 +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Add support for the CRT (Clock, Reset, and Test) controller on the Realtek
> RTD1625 SoC. This driver provides clock and reset management for the
> system, allowing peripheral clients to request necessary resources for
> operation.
> 
> 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 v5:
> - Added '#include <dt-bindings/reset/realtek,rtd1625.h>'.
> - Replaced rtk_reset_bank array with rtk_reset_desc descriptor.
> - Implemented complete a mapping table for all reset IDs.
> ---
>  drivers/clk/realtek/Kconfig           |  14 +
>  drivers/clk/realtek/Makefile          |   1 +
>  drivers/clk/realtek/clk-rtd1625-crt.c | 913 ++++++++++++++++++++++++++
>  3 files changed, 928 insertions(+)
>  create mode 100644 drivers/clk/realtek/clk-rtd1625-crt.c
> 
[...]
> diff --git a/drivers/clk/realtek/clk-rtd1625-crt.c b/drivers/clk/realtek/clk-rtd1625-crt.c
> new file mode 100644
> index 000000000000..a56978aef83a
> --- /dev/null
> +++ b/drivers/clk/realtek/clk-rtd1625-crt.c
> @@ -0,0 +1,913 @@
[...]
> +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 },
> +	/* 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 },
> +};

These should be moved into the reset driver. Then rtk_reset_desc
doesn't have to be a public interface between the clk and reset drivers
anymore.

regards
Philipp


^ permalink raw reply

* Re: [PATCH v5 03/10] reset: Add Realtek basic reset support
From: Philipp Zabel @ 2026-03-25 17:21 UTC (permalink / raw)
  To: Yu-Chun Lin, mturquette, sboyd, robh, krzk+dt, conor+dt, cylee12,
	afaerber, jyanchou
  Cc: devicetree, linux-clk, linux-kernel, linux-arm-kernel,
	linux-realtek-soc, james.tai, cy.huang, stanley_chang
In-Reply-To: <20260324025332.3416977-4-eleanor.lin@realtek.com>

On Di, 2026-03-24 at 10:53 +0800, Yu-Chun Lin wrote:
> From: Cheng-Yu Lee <cylee12@realtek.com>
> 
> Define the reset operations backed by a regmap-based register
> interface and prepare the reset controller to be registered
> through the reset framework.
> 
> 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 v5:
> - Created drivers/reset/realtek/ directory and include/linux/reset/realtek.h.
> - Extracted the common reset helpers:
>  - Moved the source code to drivers/reset/realtek/common.c and
>  - the header to include/linux/reset/realtek.h
> - Renamed rtk_reset_bank to rtk_reset_desc.
> - Added 'bits' member to rtk_reset_desc structure.
> - Removed rtk_reset_get_id() and rtk_reset_get_bank() helper.
> - Introduced rtk_reset_get_desc().
> ---
>  MAINTAINERS                    |  1 +
>  drivers/reset/Kconfig          |  1 +
>  drivers/reset/Makefile         |  1 +
>  drivers/reset/realtek/Kconfig  |  3 ++
>  drivers/reset/realtek/Makefile |  2 +
>  drivers/reset/realtek/common.c | 91 ++++++++++++++++++++++++++++++++++
>  include/linux/reset/realtek.h  | 25 ++++++++++
>  7 files changed, 124 insertions(+)
>  create mode 100644 drivers/reset/realtek/Kconfig
>  create mode 100644 drivers/reset/realtek/Makefile
>  create mode 100644 drivers/reset/realtek/common.c
>  create mode 100644 include/linux/reset/realtek.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 721356d4c02c..9419b0497e0b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -22229,6 +22229,7 @@ L:	devicetree@vger.kernel.org
>  L:	linux-clk@vger.kernel.org
>  S:	Supported
>  F:	Documentation/devicetree/bindings/clock/realtek*
> +F:	drivers/reset/realtek/*
>  F:	include/dt-bindings/clock/realtek*
>  
>  REALTEK SPI-NAND
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 7ce151f6a7e4..03be1931f264 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -398,6 +398,7 @@ config RESET_ZYNQMP
>  
>  source "drivers/reset/amlogic/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
> +source "drivers/reset/realtek/Kconfig"
>  source "drivers/reset/spacemit/Kconfig"
>  source "drivers/reset/starfive/Kconfig"
>  source "drivers/reset/sti/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index fc0cc99f8514..4407d1630070 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -2,6 +2,7 @@
>  obj-y += core.o
>  obj-y += amlogic/
>  obj-y += hisilicon/
> +obj-y += realtek/
>  obj-y += spacemit/
>  obj-y += starfive/
>  obj-y += sti/
> diff --git a/drivers/reset/realtek/Kconfig b/drivers/reset/realtek/Kconfig
> new file mode 100644
> index 000000000000..99a14d355803
> --- /dev/null
> +++ b/drivers/reset/realtek/Kconfig
> @@ -0,0 +1,3 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config RESET_RTK_COMMON
> +	bool
> diff --git a/drivers/reset/realtek/Makefile b/drivers/reset/realtek/Makefile
> new file mode 100644
> index 000000000000..b59a3f7f2453
> --- /dev/null
> +++ b/drivers/reset/realtek/Makefile
> @@ -0,0 +1,2 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +obj-$(CONFIG_RESET_RTK_COMMON) += common.o
> diff --git a/drivers/reset/realtek/common.c b/drivers/reset/realtek/common.c
> new file mode 100644
> index 000000000000..b9e3219dc8f7
> --- /dev/null
> +++ b/drivers/reset/realtek/common.c
> @@ -0,0 +1,91 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2019 Realtek Semiconductor Corporation
> + */
> +
> +#include <linux/device.h>
> +#include <linux/of.h>
> +#include <linux/regmap.h>
> +#include <linux/reset-controller.h>
> +#include <linux/reset/realtek.h>
> +
> +struct rtk_reset_data {
> +	struct reset_controller_dev rcdev;
> +	struct rtk_reset_desc *descs;
> +	struct regmap *regmap;
> +};
> +
> +static inline struct rtk_reset_data *to_rtk_reset_controller(struct reset_controller_dev *r)
> +{
> +	return container_of(r, struct rtk_reset_data, rcdev);
> +}
> +
> +static inline struct rtk_reset_desc *rtk_reset_get_desc(struct rtk_reset_data *data,
> +							unsigned long idx)
> +{
> +	return &data->descs[idx];
> +}
> +
> +static int rtk_reset_assert(struct reset_controller_dev *rcdev,
> +			    unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 mask = desc->write_en ? (0x3 << desc->bit) : BIT(desc->bit);
> +	u32 val  = desc->write_en ? (0x2 << desc->bit) : 0;
> +
> +	return regmap_update_bits(data->regmap, desc->ofs, mask, val);
> +}
> +
> +static int rtk_reset_deassert(struct reset_controller_dev *rcdev,
> +			      unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 mask = desc->write_en ? (0x3 << desc->bit) : BIT(desc->bit);
> +	u32 val  = mask;
> +
> +	return regmap_update_bits(data->regmap, desc->ofs, mask, val);
> +}
> +
> +static int rtk_reset_status(struct reset_controller_dev *rcdev,
> +			    unsigned long idx)
> +{
> +	struct rtk_reset_data *data = to_rtk_reset_controller(rcdev);
> +	struct rtk_reset_desc *desc = rtk_reset_get_desc(data, idx);
> +	u32 val;
> +	int ret;
> +
> +	ret = regmap_read(data->regmap, desc->ofs, &val);
> +	if (ret)
> +		return ret;
> +
> +	return !((val >> desc->bit) & 1);
> +}
> +
> +static const struct reset_control_ops rtk_reset_ops = {
> +	.assert   = rtk_reset_assert,
> +	.deassert = rtk_reset_deassert,
> +	.status   = rtk_reset_status,
> +};
> +
> +int rtk_reset_controller_add(struct device *dev,
> +			     struct rtk_reset_initdata *initdata)
> +{
> +	struct rtk_reset_data *data;
> +
> +	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
> +	if (!data)
> +		return -ENOMEM;
> +
> +	data->regmap          = initdata->regmap;
> +	data->descs           = initdata->descs;
> +	data->rcdev.owner     = THIS_MODULE;
> +	data->rcdev.ops       = &rtk_reset_ops;
> +	data->rcdev.dev       = dev;
> +	data->rcdev.of_node   = dev->of_node;
> +	data->rcdev.nr_resets = initdata->num_descs;
> +
> +	return devm_reset_controller_register(dev, &data->rcdev);
> +}
> +EXPORT_SYMBOL_GPL(rtk_reset_controller_add);

Please implement this as an auxiliary device driver. Move the
rtk_reset_initdata definitions in here and select them based on either
auxiliary_device_id (see imx8mp-audiomix or spacemit) or of_device_id
(see eyeq).
The regmap can be retrieved from the parent (clk device) via
dev_get_regmap (see imx8mp-audiomix).

> diff --git a/include/linux/reset/realtek.h b/include/linux/reset/realtek.h
> new file mode 100644
> index 000000000000..3c2226e3ed26
> --- /dev/null
> +++ b/include/linux/reset/realtek.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __LINUX_RESET_REALTEK_H__
> +#define __LINUX_RESET_REALTEK_H__
> +
> +#include <linux/types.h>
> +
> +struct device;
> +struct regmap;
> +
> +struct rtk_reset_desc {
> +	u32 ofs;
> +	u32 bit;
> +	u32 write_en;
> +};
> +
> +struct rtk_reset_initdata {
> +	struct rtk_reset_desc *descs;
> +	u32 num_descs;
> +	struct regmap *regmap;
> +};
> +
> +int rtk_reset_controller_add(struct device *dev,
> +			     struct rtk_reset_initdata *initdata);
> +
> +#endif /* __LINUX_RESET_REALTEK_H__ */

With the above suggested changes, this header is not necessary.

regards
Philipp


^ permalink raw reply

* Re: [PATCH] i2c: s3c24xx: check the size of the SMBUS message before using it
From: Andi Shyti @ 2026-03-25 17:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-arm-kernel, linux-samsung-soc, linux-i2c, linux-kernel,
	Krzysztof Kozlowski, Alim Akhtar, stable
In-Reply-To: <2026022314-rely-scrubbed-4839@gregkh>

Hi Greg,

On Mon, Feb 23, 2026 at 06:05:15PM +0100, Greg Kroah-Hartman wrote:
> The first byte of an i2c SMBUS message is the size, and it should be
> verified to ensure that it is in the range of 0..I2C_SMBUS_BLOCK_MAX
> before processing it.
> 
> This is the same logic that was added in commit a6e04f05ce0b ("i2c:
> tegra: check msg length in SMBUS block read") to the i2c tegra driver.
> 
> Cc: Krzysztof Kozlowski <krzk@kernel.org>
> Cc: Alim Akhtar <alim.akhtar@samsung.com>
> Cc: Andi Shyti <andi.shyti@kernel.org>
> Cc: stable <stable@kernel.org>
> Assisted-by: gkh_clanker_2000
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

merged to i2c/i2c-host.

Thanks,
Andi


^ permalink raw reply

* Re: [PATCH v4 8/9] dt-bindings: net: wireless: brcm: Add compatible for bcm43752
From: Rob Herring @ 2026-03-25 17:09 UTC (permalink / raw)
  To: Ronald Claveau
  Cc: Neil Armstrong, Kevin Hilman, Jerome Brunet, Martin Blumenstingl,
	Krzysztof Kozlowski, Conor Dooley, Ulf Hansson, Johannes Berg,
	van Spriel, linux-arm-kernel, linux-amlogic, devicetree,
	linux-kernel, linux-mmc, linux-wireless
In-Reply-To: <20260325-add-emmc-t7-vim4-v4-8-44c7b4a5e459@aliel.fr>

On Wed, Mar 25, 2026 at 10:15:26AM +0100, Ronald Claveau wrote:
> Add bcm43752 compatible with its bcm4329 compatible fallback.
> 
> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>

Missing Conor's ack.

> ---
>  Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> index 3be7576787644..81fd3e37452a6 100644
> --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm4329-fmac.yaml
> @@ -42,6 +42,7 @@ properties:
>                - brcm,bcm4356-fmac
>                - brcm,bcm4359-fmac
>                - brcm,bcm4366-fmac
> +              - brcm,bcm43752-fmac
>                - cypress,cyw4373-fmac
>                - cypress,cyw43012-fmac
>                - infineon,cyw43439-fmac
> 
> -- 
> 2.49.0
> 


^ permalink raw reply

* Re: [PATCH v2] ARM: dts: imx: Add DT overlays for DH i.MX6 DHCOM SoM and boards
From: Frank Li @ 2026-03-25 17:02 UTC (permalink / raw)
  To: linux-arm-kernel, Marek Vasut
  Cc: Frank Li, Christoph Niedermaier, Conor Dooley, Fabio Estevam,
	Krzysztof Kozlowski, Pengutronix Kernel Team, Rob Herring,
	Sascha Hauer, devicetree, imx, kernel, linux-kernel
In-Reply-To: <20260324190356.74293-1-marex@nabladev.com>


On Tue, 24 Mar 2026 20:03:11 +0100, Marek Vasut wrote:
> Add DT overlays to support DH i.MX6 DHCOM SoM carrier board expansion
> modules. The following DT overlays are implemented:
> - PDK2:
>   - DH 497-200 Display board in edge connector X12
>   - DH 505-200 Display board in edge connector X12
>   - DH 531-100 SPI/I2C board in header X21
>   - DH 531-200 SPI/I2C board in header X22
>   - DH 560-200 Display board in edge connector X12
> - PicoITX:
>   - DH 626-100 Display board in edge connector X2
>
> [...]

Applied, thanks!

[1/1] ARM: dts: imx: Add DT overlays for DH i.MX6 DHCOM SoM and boards
      commit: 7bc76d413dbe6631a207b38aa67b2d00fdc27b2c

move status = "okay" to last property.

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [PATCH v3 0/7] arm64: dts: imx943: various update
From: Frank Li @ 2026-03-25 16:55 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Peng Fan (OSS)
  Cc: Frank Li, devicetree, imx, linux-arm-kernel, linux-kernel,
	Peng Fan, Ranjani Vaidyanathan, Joy Zou, Florin Leotescu
In-Reply-To: <20260324-imx943-dts-v1-v3-0-b33bf1f1c254@nxp.com>


On Tue, 24 Mar 2026 13:44:06 +0800, Peng Fan (OSS) wrote:
> Update pin header
> Add V2X/ELE mailbox nodes, more SCMI nodes, thermal nodes, fan node
> Add nxp,ctrl-ids.
>
>

Applied, thanks!

[1/7] arm64: dts: imx94: Update pin headers
      commit: 91faaca1db2ff31dd9a964c419ea39dcb396022f
[2/7] arm64: dts: imx94: Add V2X/ELE mailbox nodes
      commit: 87ac991725ccc441af0fc16d54f9cee7e05bd4a2
[3/7] arm64: dts: imx94: Add SCMI sensor/lmm/cpu nodes
      commit: dee18abd657f2cf5c1540eafadfdeb9444f4721d
[4/7] arm64: dts: imx943: Add thermal support
      commit: 81b428c2a761d9f40fb95eb0c556544541988263
[5/7] arm64: dts: imx943-evk: Add nxp,ctrl-ids for scmi_misc
      commit: a2cdee4ce35863e0e6d4f58808f8e051b9608073
[6/7] arm64: dts: imx943-evk: Add fan node and enable active cooling on A55
      commit: 12cac5ae8bc741de9b03a2c23d128bfaf0c4c4ce

Adjust pwm@2f after codec@1a keep order by address

[7/7] arm64: dts: imx943-evk: Add pf09/53 thermal zone
      commit: bd25e888974ffa2e6097b2ee352c8f6f860f5e87

Add extra empty line between children node trips and properties.

Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* Re: [PATCH RESEND 1/2] regulator: dt-bindings: mt6315: Add regulator supplies
From: Mark Brown @ 2026-03-25 16:55 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Chen-Yu Tsai, Liam Girdwood, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek, devicetree
In-Reply-To: <20260325-uncovered-carp-of-inquire-8a7acf@quoll>

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

On Wed, Mar 25, 2026 at 09:56:00AM +0100, Krzysztof Kozlowski wrote:
> On Tue, Mar 24, 2026 at 01:30:28PM +0800, Chen-Yu Tsai wrote:

> > +      pvdd4-supply:
> > +        description: Supply for vbuck4

> These all look per-regulator supplies, so I think they should be in each
> regulator node (see also regulator.yaml).

> Or in top-level, but not in "regulators" node. The regulators is only
> wrapping node for children.

> I wonder what should be our preference - have supplies per regulator or
> in top-level node. @Mark, any preference from your side?

The top level, so people can figure out where to describe supplies
without having to read the bindings so much - the supplies go into the
chip, even if they're distributed within it.

Please don't add random characters to my name.

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

^ permalink raw reply

* Re: [PATCH v27 2/4] dt-bindings: i2c: ast2600-i2c.yaml: Add global-regs and transfer-mode properties
From: Rob Herring @ 2026-03-25 16:52 UTC (permalink / raw)
  To: Ryan Chen
  Cc: Jeremy Kerr, andriy.shevchenko@linux.intel.com, Andi Shyti,
	Krzysztof Kozlowski, Conor Dooley, Joel Stanley, Andrew Jeffery,
	Benjamin Herrenschmidt, Rayn Chen, Philipp Zabel,
	linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org,
	linux-aspeed@lists.ozlabs.org, linux-kernel@vger.kernel.org,
	openbmc@lists.ozlabs.org
In-Reply-To: <TY2PPF5CB9A1BE6F0B9087048F46ABD72A6F249A@TY2PPF5CB9A1BE6.apcprd06.prod.outlook.com>

On Wed, Mar 25, 2026 at 08:11:54AM +0000, Ryan Chen wrote:
> Hello Jeremy,
> 	Thanks the review.
> 
> > Subject: Re: [PATCH v27 2/4] dt-bindings: i2c: ast2600-i2c.yaml: Add global-regs
> > and transfer-mode properties
> > 
> > Hi Ryan,
> > 
> > > The AST2600 I2C controller supports three transfer modes (byte,
> > > buffer, DMA). Add "aspeed,transfer-mode" so DT can select the
> > > preferred transfer method per controller instance.
> > 
> > This patch does not add an aspeed,transfer-mode property.
> Will update use aspeed,enable-dma

[...]

> > > +  aspeed,enable-dma:
> > > +    type: boolean
> > > +    description: |
> > > +      I2C bus enable dma mode transfer.
> > > +
> > > +      ASPEED ast2600 platform equipped with 16 I2C controllers that
> > > +share a
> > > +      single DMA engine. DTS files can specify the data transfer mode
> > > +to/from
> > > +      the device, either DMA or programmed I/O.
> > 
> > As we had discussed: this does not define the transfer mode, only whether
> > DMA is available to the peripheral.
> > 
> > Why mention the 16 i2c controllers here?
> > 
> > Please keep this description simple and relevant to the specific purpose of the
> > property.
> 
> Will update with following.
> description: Enable DMA for transfers on this I2C bus.

You still don't understand the distinction. It's not enable, but that 
the h/w instance *has* DMA capability or not. It is still up to the OS 
what to do with that information.

Rob


^ permalink raw reply

* Re: [PATCH v13 3/6] iommu: Add verisilicon IOMMU driver
From: Will Deacon @ 2026-03-25 16:36 UTC (permalink / raw)
  To: Benjamin Gaignard
  Cc: joro, robin.murphy, robh, krzk+dt, conor+dt, heiko,
	nicolas.dufresne, p.zabel, mchehab, iommu, devicetree,
	linux-kernel, linux-arm-kernel, linux-rockchip, linux-media
In-Reply-To: <e083e933-2746-4b26-ac33-3b32d362b28e@collabora.com>

On Tue, Mar 24, 2026 at 05:28:44PM +0100, Benjamin Gaignard wrote:
> 
> Le 24/03/2026 à 16:46, Will Deacon a écrit :
> > On Mon, Feb 16, 2026 at 10:51:35AM +0100, Benjamin Gaignard wrote:
> > > The Verisilicon IOMMU hardware block can be found in combination
> > > with Verisilicon hardware video codecs (encoders or decoders) on
> > > different SoCs.
> > > Enable it will allow us to use non contiguous memory allocators
> > > for Verisilicon video codecs.
> > > If both decoder and this iommu driver are compiled has modules
> > > there is undefined symboles issues so this iommu driver could
> > > only be compiled has built-in.
> > > 
> > > Signed-off-by: Benjamin Gaignard <benjamin.gaignard@collabora.com>
> > > ---
> > >   MAINTAINERS               |   8 +
> > >   drivers/iommu/Kconfig     |  11 +
> > >   drivers/iommu/Makefile    |   1 +
> > >   drivers/iommu/vsi-iommu.c | 794 ++++++++++++++++++++++++++++++++++++++
> > >   include/linux/vsi-iommu.h |  21 +
> > >   5 files changed, 835 insertions(+)
> > >   create mode 100644 drivers/iommu/vsi-iommu.c
> > >   create mode 100644 include/linux/vsi-iommu.h
> > [...]
> > 
> > > +static size_t vsi_iommu_unmap(struct iommu_domain *domain, unsigned long _iova,
> > > +			      size_t size, size_t count, struct iommu_iotlb_gather *gather)
> > > +{
> > > +	struct vsi_iommu_domain *vsi_domain = to_vsi_domain(domain);
> > > +	dma_addr_t pte_dma, iova = (dma_addr_t)_iova;
> > > +	unsigned long flags;
> > > +	phys_addr_t pt_phys;
> > > +	u32 dte;
> > > +	u32 *pte_addr;
> > > +	size_t unmap_size = 0;
> > > +
> > > +	spin_lock_irqsave(&vsi_domain->lock, flags);
> > > +
> > > +	dte = vsi_domain->dt[vsi_iova_dte_index(iova)];
> > > +	/* Just return 0 if iova is unmapped */
> > > +	if (!vsi_dte_is_pt_valid(dte))
> > > +		goto unlock;
> > > +
> > > +	pt_phys = vsi_dte_pt_address(dte);
> > > +	pte_addr = (u32 *)phys_to_virt(pt_phys) + vsi_iova_pte_index(iova);
> > > +	pte_dma = pt_phys + vsi_iova_pte_index(iova) * sizeof(u32);
> > > +	unmap_size = vsi_iommu_unmap_iova(vsi_domain, pte_addr, pte_dma, size);
> > > +
> > > +unlock:
> > > +	spin_unlock_irqrestore(&vsi_domain->lock, flags);
> > > +
> > > +	return unmap_size;
> > > +}
> > I still think you need TLB invalidation here.
> > 
> > I looked at the downstream code that you linked to and it litters the
> > invalidation in the callers via mpp_iommu_flush_tlb(), which tend to
> > invalidate _before_ starting an operation. That's very likely buggy and
> > certainly not something we want upstream.
> > 
> > The unmap routine should do the invalidation so that, when it returns,
> > the pages really are unmapped from the device (assuming strict mode).
> > 
> > I know you said that you tried to add invalidation here and it "didn't
> > work", but that's not something I can really help you with.
> 
> I know you expect the hardware to work like that but that isn't not the
> case.

The hardware appears to have a register to invalidate the entire TLB.
We can use that if there's nothing else.

> I spend quite long to try to found hidden bit(s) or an other way to do like
> you want but I can't find any solution.

Then we can invalidate the entire TLB.

> As you mention the downstream code suggest that the iommu can't invalidate
> TLB in unmap routine so I don't see how to progress.

The downstream code is a tangled mess; I don't think it suggests anything
about what the IOMMU hardware is capable of.

> Maybe we should just admit that is how the hardware work.

No.

The upstream kernel isn't a dumping ground for vendor crap. The hardware
has TLB invalidation functionality and so we should use it. If we don't,
then we're not giving the IOMMU API what it expects and any callers
outside of the video codecs will be landed with problems when unmap
doesn't work as expected.

> This v13 has fixed the documentation so I don't plan to spend more time on this driver.

That's a shame, I'm really not asking for much.

Will


^ permalink raw reply

* Re: [PATCH v3] arm64: dts: imx8mp-frdm: add sd, ethernet, wifi, usb and hdmi support
From: Frank Li @ 2026-03-25 16:35 UTC (permalink / raw)
  To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Fabian Pfitzner
  Cc: Frank Li, devicetree, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <20260325-fpf-imx8mp-frdm-v3-1-1c98eade991a@pengutronix.de>


On Wed, 25 Mar 2026 17:01:49 +0100, Fabian Pfitzner wrote:
> Add support for the following new features:
>
> - SD Card
> - Ethernet (FEC + EQOS)
> - Wifi
> - USB
> - HDMI
>
> [...]

Applied, thanks!

[1/1] arm64: dts: imx8mp-frdm: add sd, ethernet, wifi, usb and hdmi support
      commit: 961719c5456ce407221868d9cab2a1311ccf1eeb

Remove extra line before &hdmi_pvi
move usb* node before usdhc1 to keep alphabet order.


Best regards,
--
Frank Li <Frank.Li@nxp.com>


^ permalink raw reply

* [PATCH 1/1] clk: scmi: Add error message if SCMI protocol handler could not be found
From: Alexander Stein @ 2026-03-25 16:35 UTC (permalink / raw)
  To: Sudeep Holla, Cristian Marussi, Michael Turquette, Stephen Boyd
  Cc: Alexander Stein, arm-scmi, linux-arm-kernel, linux-clk,
	linux-kernel

In case the protocol could not be found an error message is better than
probe just failing with error code -22.

Signed-off-by: Alexander Stein <alexander.stein@ew.tq-group.com>
---
 drivers/clk/clk-scmi.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 7c562559ad8bb..c32b15b272ccd 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -384,7 +384,8 @@ static int scmi_clocks_probe(struct scmi_device *sdev)
 	scmi_proto_clk_ops =
 		handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
 	if (IS_ERR(scmi_proto_clk_ops))
-		return PTR_ERR(scmi_proto_clk_ops);
+		return dev_err_probe(dev, PTR_ERR(scmi_proto_clk_ops),
+				     "No SCMI protocol handler found\n");
 
 	count = scmi_proto_clk_ops->count_get(ph);
 	if (count < 0) {
-- 
2.43.0



^ permalink raw reply related


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