Linux Documentation
 help / color / mirror / Atom feed
* [PATCH v5 1/8] dt-bindings: riscv: Add Ssqosid extension description
From: Drew Fustini @ 2026-07-15  0:23 UTC (permalink / raw)
  To: Adrien Ricciardi, Alexandre Ghiti, Atish Kumar Patra, Atish Patra,
	Babu Moger, Ben Horgan, Borislav Petkov, Chen Pei, Conor Dooley,
	Conor Dooley, Dave Hansen, Dave Martin, Fenghua Yu, Gong Shuai,
	Gong Shuai, guo.wenjia23, James Morse, Kornel Dulęba,
	Krzysztof Kozlowski, liu.qingtao2, Liu Zhiwei, Palmer Dabbelt,
	Paul Walmsley, Peter Newman, Radim Krčmář,
	Reinette Chatre, Rob Herring, Samuel Holland,
	Sebastian Andrzej Siewior, Tony Luck, Vasudevan Srinivasan,
	Ved Shanbhogue, Weiwei Li, yunhui cui, Zhanpeng Zhang,
	Drew Fustini
  Cc: linux-kernel, linux-riscv, x86, devicetree, linux-rt-devel,
	linux-doc
In-Reply-To: <20260714-dfustini-atl-sc-cbqri-dt-v5-0-b0ae7e9c932e@kernel.org>

Document the ratified Supervisor-mode Quality of Service ID (Ssqosid)
extension v1.0.

Link: https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: Drew Fustini <fustini@kernel.org>
---
 Documentation/devicetree/bindings/riscv/extensions.yaml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 5ffc40d599c0..c9dc5d80c0ea 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -232,6 +232,12 @@ properties:
             ratified at commit d70011dde6c2 ("Update to ratified state")
             of riscv-j-extension.
 
+        - const: ssqosid
+          description: |
+            The standard Ssqosid extension for Quality of Service ID is
+            ratified as v1.0 in commit d9c616497fde ("Merge pull
+            request #7 from ved-rivos/Ratified") of riscv-ssqosid.
+
         - const: ssstateen
           description: |
             The standard Ssstateen extension for supervisor-mode view of the

-- 
2.43.0


^ permalink raw reply related

* [PATCH v5 0/8] riscv: Add Ssqosid and initial CBQRI resctrl support
From: Drew Fustini @ 2026-07-15  0:23 UTC (permalink / raw)
  To: Adrien Ricciardi, Alexandre Ghiti, Atish Kumar Patra, Atish Patra,
	Babu Moger, Ben Horgan, Borislav Petkov, Chen Pei, Conor Dooley,
	Conor Dooley, Dave Hansen, Dave Martin, Fenghua Yu, Gong Shuai,
	Gong Shuai, guo.wenjia23, James Morse, Kornel Dulęba,
	Krzysztof Kozlowski, liu.qingtao2, Liu Zhiwei, Palmer Dabbelt,
	Paul Walmsley, Peter Newman, Radim Krčmář,
	Reinette Chatre, Rob Herring, Samuel Holland,
	Sebastian Andrzej Siewior, Tony Luck, Vasudevan Srinivasan,
	Ved Shanbhogue, Weiwei Li, yunhui cui, Zhanpeng Zhang,
	Drew Fustini
  Cc: linux-kernel, linux-riscv, x86, devicetree, linux-rt-devel,
	linux-doc

This series adds initial RISC-V QoS support: the Ssqosid extension [1]
(srmcfg CSR), the CBQRI controller interface [2] integrated with resctrl
[3], and a DT-based platform driver for cache controllers. It has been
tested on both the Tenstorrent Ascalon Shared Cache controller and a QEMU
implementation [4].

  qemu-system-riscv64 -M virt,aia=aplic-imsic -nographic -m 1G -smp 8 \
      -kernel arch/riscv/boot/Image \
      -append "root=/dev/vda ro console=ttyS0 rootwait" \
      -drive if=none,file=rootfs.ext2,format=raw,id=hd0 \
      -device virtio-blk-device,drive=hd0 \
      -device riscv.cbqri.capacity,max_mcids=256,max_rcids=64,ncblks=16,mmio_base=0x04820000

Cache allocation can be exercised on the booted system. Mount resctrl
and read the default schemata. The L2 controller has 16 capacity
blocks, so the default capacity bitmask (CBM) is 0xffff:

  # mount -t resctrl resctrl /sys/fs/resctrl
  # cat /sys/fs/resctrl/schemata
  L2:0=ffff

Write a narrower CBM to a new control group and read it back to confirm
the L2 controller applied it:

  # mkdir /sys/fs/resctrl/group0
  # echo "L2:0=ff" > /sys/fs/resctrl/group0/schemata
  # cat /sys/fs/resctrl/group0/schemata
  L2:0=ff

Note that this series only implements support for resctrl L2 and L3
cache resources using CBQRI capacity allocation control. cc_block_mask
maps onto resctrl's existing cbm schema. However, cc_cunits is not
supported as there is no existing equivalent for capacity units in the
resctrl schemata.

I had previously been iterating on an RFC series [5] that did a full
implementation of CBQRI including capacity monitoring, bandwidth
allocation and monitoring. The bandwidth controls for CBQRI do not fit
well into resctrl's existing throttle-based MB schemata. I believe that
the path forward is Reinette's generic schema description proof of
concept [6]. My plan is to rebase the full support of CBQRI onto the
generic schema once it is ready.

This series is based on the linux-next tag next-20260713.

[1] https://github.com/riscv/riscv-ssqosid/releases/tag/v1.0
[2] https://github.com/riscv-non-isa/riscv-cbqri/releases/tag/v1.0
[3] https://docs.kernel.org/filesystems/resctrl.html
[4] https://github.com/tt-fustini/qemu/tree/riscv-cbqri-cache
[5] https://lore.kernel.org/linux-riscv/20260601-ssqosid-cbqri-rqsc-v7-0-v6-16-baf00f50028a@kernel.org/
[6] https://lore.kernel.org/all/aab804b9-e8b5-40ad-a85b-af7033391243@intel.com/

Changes in v5:
--------------
- Resolve control domain membership from each CPU's cache id in
  cacheinfo at hotplug, instead of a CPU mask captured at probe.

- Add and remove control domains on the ctrl_domains RCU list
  following the documented traversal rules.

- Restructure cbqri_resctrl_pick_caches() to select one controller per
  cache level, which removes the separate dropped[] array and the
  overloaded NULL controller pointer.

- Initialize the control domain's resource id.

- Drop the inaccurate comment above the stubbed resctrl_arch_*()
  operations.

- Sashiko review of v4:
  https://sashiko.dev/#/patchset/20260706-dfustini-atl-sc-cbqri-dt-v4-0-e75c20201d64@kernel.org

- Link to v4:
  https://patch.msgid.link/20260706-dfustini-atl-sc-cbqri-dt-v4-0-e75c20201d64@kernel.org

Changes in v4:
--------------
- Register the srmcfg PM notifier even if cpuhp_setup_state() fails in
  riscv_srmcfg_init(). The early return on failure had skipped it,
  dropping the srmcfg restore across suspend and resume.

- Make RISCV_CBQRI a user-selectable option that depends on
  RISCV_ISA_SSQOSID, instead of being selected unconditionally.

- Bound the per-domain control value init by the domain's own
  controller's RCID count rather than the resource wide count.

- Drop only the affected cache level when capacity controllers at the
  same level report mismatched capabilities, rather than aborting the
  whole resctrl setup.

- Use guard(mutex) instead of lock/unlock for cbqri_controllers_lock.

- Read the CBQRI control registers into low and high halves so the
  access order is explicit and comment on torn reads.

- Clarify in cbqri_resctrl_pick_caches() that the first matching leaf is
  correct for a unified shared cache.

- Link to v3:
  https://patch.msgid.link/20260628-dfustini-atl-sc-cbqri-dt-v3-0-c9c1342fe3cf@kernel.org

- Sashiko review of v3:
  https://sashiko.dev/#/patchset/20260628-dfustini-atl-sc-cbqri-dt-v3-0-c9c1342fe3cf@kernel.org

Changes in v3:
--------------
- riscv,cbqri.yaml:
  - Require a device-specific compatible so a bare generic compatible
    is no longer valid on its own.
  - Rename node name from cache-controller@ to qos-controller@
  - Rename compatible from tenstorrent,ascalon-sc-cbqri to
    tenstorrent,ascalon-shared-cache-controller

- Take cbqri_controllers_lock in cbqri_attach_cpu_to_all_ctrls() so a
  controller probed after boot can't corrupt the cbqri_controllers list.

- Revise comment above riscv_srmcfg_reset_cache() to clarify that the
  teardown callback is not relied on. The cpuhp startup callback re-arms
  the per-cpu sentinel, which forces the csr write on a re-onlined CPU.

- Drop the memory fences around the srmcfg CSR write on context switch.
  Ssqosid does not require the ordering. The brief tagging inaccuracy at
  the switch boundary is acceptable for QoS.

- Access the CBQRI controller registers with 32-bit reads and writes.
  The spec only guarantees single-copy atomicity for 4-byte accesses.
  This also removes the dependency on native 64-bit MMIO.

- Program cc_cunits to 0 before a config limit operation on controllers
  that support capacity units, so a stale unit limit does not constrain
  block-mask allocation.

- Link to v2:
  https://patch.msgid.link/20260624-dfustini-atl-sc-cbqri-dt-v2-0-2f8049fd902b@kernel.org

- Sashiko review of v2:
  https://sashiko.dev/#/patchset/20260624-dfustini-atl-sc-cbqri-dt-v2-0-2f8049fd902b@kernel.org

Changes in v2:
--------------
The changes in this revision address the Sashiko review of v1.

- Restore the srmcfg CSR for the current task on CPU_PM_EXIT and
  CPU_PM_ENTER_FAILED, so it is not left configured incorrectly until
  the next context switch.

- Serialize the cbqri_controllers list insert and the boot time walk
  with a mutex, so an asynchronous driver probe cannot corrupt the list.

- Skip a controller at an unsupported cache level instead of aborting
  resctrl setup, so valid L2 and L3 controllers still register.

- RISCV_ISA_SSQOSID selects ARCH_HAS_CPU_RESCTRL and RISCV_CBQRI
  together, so no intermediate commit enables RESCTRL_FS without the
  CBQRI resctrl glue.

- Rename the RISCV_CBQRI_DRIVER to RISCV_CBQRI, since it builds the
  CBQRI core ops and resctrl integration rather than a driver.

- Drop the RISCV_CBQRI_DRIVER_DEBUG Kconfig option and rely on dynamic
  debug to control the pr_debug() output.

- Note: Sashiko flagged the lack of suspend/resume state restore. I will
  not fix that as register state is only lost when the power domain is
  gated, which offlines the harts sharing the cache. resctrl reprograms
  the default capacity mask through the normal control domain online
  path on resume.

- Link to v1:
  https://lore.kernel.org/all/20260619-dfustini-atl-sc-cbqri-dt-v1-0-e79a7723fab0@kernel.org/

- Sashiko review of v1:
  https://sashiko.dev/#/patchset/20260619-dfustini-atl-sc-cbqri-dt-v1-0-e79a7723fab0@kernel.org

---
Drew Fustini (8):
      dt-bindings: riscv: Add Ssqosid extension description
      riscv: Detect the Ssqosid extension
      riscv: Add support for srmcfg CSR from Ssqosid extension
      riscv_cbqri: Add capacity controller probe and allocation device ops
      riscv_cbqri: resctrl: Add cache allocation via capacity block mask
      riscv: Enable resctrl filesystem for Ssqosid
      dt-bindings: riscv: Add binding for CBQRI controllers
      riscv_cbqri: Add CBQRI capacity allocation platform driver

 .../devicetree/bindings/riscv/extensions.yaml      |   6 +
 .../devicetree/bindings/riscv/riscv,cbqri.yaml     |  97 +++
 MAINTAINERS                                        |  15 +
 arch/riscv/Kconfig                                 |  18 +
 arch/riscv/include/asm/csr.h                       |   5 +
 arch/riscv/include/asm/hwcap.h                     |   1 +
 arch/riscv/include/asm/processor.h                 |   3 +
 arch/riscv/include/asm/qos.h                       |  74 ++
 arch/riscv/include/asm/resctrl.h                   | 147 ++++
 arch/riscv/include/asm/switch_to.h                 |   3 +
 arch/riscv/kernel/Makefile                         |   2 +
 arch/riscv/kernel/cpufeature.c                     |   1 +
 arch/riscv/kernel/qos.c                            | 101 +++
 drivers/resctrl/Kconfig                            |  30 +
 drivers/resctrl/Makefile                           |   5 +
 drivers/resctrl/cbqri_capacity.c                   | 127 ++++
 drivers/resctrl/cbqri_devices.c                    | 563 +++++++++++++++
 drivers/resctrl/cbqri_internal.h                   | 122 ++++
 drivers/resctrl/cbqri_resctrl.c                    | 785 +++++++++++++++++++++
 include/linux/riscv_cbqri.h                        |  45 ++
 20 files changed, 2150 insertions(+)
---
base-commit: 49362394dad7df66c274c867a271394c10ca2bb8
change-id: 20260610-dfustini-atl-sc-cbqri-dt-410c8e2711dd

Best regards,
--  
Drew Fustini <fustini@kernel.org>


^ permalink raw reply

* Re: [PATCH v5 0/3] x86,fs/resctrl,arm_mpam: Factor MBA parse-time conversion to be per-arch
From: Gavin Shan @ 2026-07-15  0:13 UTC (permalink / raw)
  To: Ben Horgan
  Cc: james.morse, reinette.chatre, fenghuay, linux-kernel,
	linux-arm-kernel, tglx, mingo, bp, dave.hansen, hpa, corbet, x86,
	linux-doc, dave.martin
In-Reply-To: <20260709093111.367851-1-ben.horgan@arm.com>

On 7/9/26 7:31 PM, Ben Horgan wrote:
> This version fixes a couple of non-functional mistakes in v4 pointed out by Reinette.
> 
> The patches should stay together so please could this all go via tip.
> 
> Changelogs in patches.
> 
>  From cover letter of v3:
> 
> This is a new version of Dave Martin's patch [1] to delegate rounding of
> bandwidth control user values to the arch code. As there is now more than one
> architecture using resctrl, I split the original patch into two, a core resctrl
> patch and an x86 patch, and added an MPAM patch. Please let me know if the patch
> break down and ordering is sensible and whether the pattern should be followed
> for any future similar changes.
> 
> This does have a user visible effect on MB schema when using MPAM hardware
> with 'bandwidth_gran' greater than 1. I'm not sure if MPAM hardware with such
> coarse controls exists in the wild but it is spec compliant and I've tested it
> on a model.
> 
> [1] https://lore.kernel.org/lkml/20251031154225.14799-1-Dave.Martin@arm.com/
> 
> v3: https://lore.kernel.org/lkml/20260515140612.1205251-1-ben.horgan@arm.com/
> v4: https://lore.kernel.org/lkml/20260706160639.2136674-1-ben.horgan@arm.com/
> 
> Based on v7.2-rc2
> 
> Ben Horgan (1):
>    arm_mpam: resctrl: Add pass-through resctrl_arch_preconvert_bw()
> 
> Dave Martin (2):
>    x86,fs/resctrl: Add resctrl_arch_preconvert_bw()
>    fs/resctrl: Factor MBA parse-time conversion to be per-arch
> 
>   Documentation/filesystems/resctrl.rst     | 17 +++++++++--------
>   arch/x86/kernel/cpu/resctrl/ctrlmondata.c |  6 ++++++
>   drivers/resctrl/mpam_resctrl.c            |  5 +++++
>   fs/resctrl/ctrlmondata.c                  |  6 +++---
>   include/linux/resctrl.h                   | 19 +++++++++++++++++++
>   5 files changed, 42 insertions(+), 11 deletions(-)
> 

Looks good in my tests on NVidia's grace-hopper machine. No errors found
from the kunit-tests and the MBW limiting works with more precise granularity.
The code changes look good to me either.

Tested-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>

Thanks,
Gavin


^ permalink raw reply

* Re: [PATCH v5 0/3] x86,fs/resctrl,arm_mpam: Factor MBA parse-time conversion to be per-arch
From: Reinette Chatre @ 2026-07-14 23:59 UTC (permalink / raw)
  To: Moger, Babu, Ben Horgan, bp, x86
  Cc: james.morse, fenghuay, linux-kernel, linux-arm-kernel, tglx,
	mingo, dave.hansen, hpa, corbet, linux-doc, dave.martin
In-Reply-To: <2cad039a-63ee-4340-a9f7-d8aaeeda593a@amd.com>



On 7/14/26 3:48 PM, Moger, Babu wrote:
> Ran few tests on the series. Everything looks good.
> 
> Tested-by: Babu Moger <babu.moger@amd.com>
> 
Thank you very much Babu.

Reinette

^ permalink raw reply

* [PATCH v2] KVM: arm64: vgic: Avoid double-deactivate of IRQs in the nested context.
From: D Scott Phillips @ 2026-07-14 23:11 UTC (permalink / raw)
  To: Marc Zyngier, Oliver Upton, Catalin Marinas, Will Deacon,
	Jonathan Corbet, Shuah Khan, Joey Gouly, Steffen Eiden,
	Suzuki K Poulose, Zenghui Yu
  Cc: Mark Rutland, Zeng Heng, Wei Xu, Vladimir Murzin, Lucas Wei,
	Kuninori Morimoto, Sascha Bischoff, Yicong Yang, Yeoreum Yun,
	linux-arm-kernel, linux-doc, linux-kernel, kvmarm

In the nested state, the physical interrupt has already been
deactivated through the HW bit in the LR. The extra deactivation
would be harmless but can hit an errata case on AmpereOne, so
avoid it here.

On AmpereOne, deactivating a physical interrupt through
ICC_DIR_EL1 or ICC_EOIR1_EL1 (depending on EOImode) which is not
active, but is the highest priority pending interrupt causes the
cpu to lose the interrupt pending state and also prevents the
delivery of future interrupts.

Fixes: 6dd333c8942b2 ("KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive")
Signed-off-by: D Scott Phillips <scott@os.amperecomputing.com>
Cc: stable@vger.kernel.org
---
Link to v1: https://lore.kernel.org/linux-arm-kernel/20260710222128.416581-1-scott@os.amperecomputing.com/
Changes since v1:
 - Drop erratum cpucap
 - Add comment about errata at change
 - Update commit message with description from Marc, add Fixes:

 Documentation/arch/arm64/silicon-errata.rst | 4 ++++
 arch/arm64/kvm/vgic/vgic-v3.c               | 8 +++++++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 014aa1c215a16..88b4aa45a2066 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -55,10 +55,14 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Ampere         | AmpereOne       | AC03_CPU_38     | AMPERE_ERRATUM_AC03_CPU_38  |
 +----------------+-----------------+-----------------+-----------------------------+
+| Ampere         | AmpereOne       | AC03_CPU_57     | N/A                         |
++----------------+-----------------+-----------------+-----------------------------+
 | Ampere         | AmpereOne AC04  | AC04_CPU_10     | AMPERE_ERRATUM_AC03_CPU_38  |
 +----------------+-----------------+-----------------+-----------------------------+
 | Ampere         | AmpereOne AC04  | AC04_CPU_23     | AMPERE_ERRATUM_AC04_CPU_23  |
 +----------------+-----------------+-----------------+-----------------------------+
+| Ampere         | AmpereOne AC04  | AC04_CPU_29     | N/A                         |
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2457168        | ARM64_ERRATUM_2457168       |
 +----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index 9e841e7afd4a7..7aa417440f6a2 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -275,7 +275,13 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
 		lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
 	}
 
-	if (lr & ICH_LR_HW)
+	/*
+	 * In the nested state, the irq has already been deactivated via the HW
+	 * bit in the LR. Deactivating again would be harmless except AmpereOne
+	 * errata AC03_CPU_57, AC04_CPU_29 could cause irq delivery to break if
+	 * the deactivation hits the highest priority pending irq.
+	 */
+	if ((lr & ICH_LR_HW) && !vgic_state_is_nested(vcpu))
 		vgic_v3_deactivate_phys(FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
 
 	vgic_v3_fold_lr(vcpu, lr);
-- 
2.55.0


^ permalink raw reply related

* Re: [PATCH] arm64: errata: Mitigate AmpereOne erratum AC03_CPU_57 and AC04_CPU_29
From: D Scott Phillips @ 2026-07-14 23:06 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Oliver Upton, Catalin Marinas, Will Deacon, Jonathan Corbet,
	Shuah Khan, Joey Gouly, Steffen Eiden, Suzuki K Poulose,
	Zenghui Yu, Mark Rutland, Zeng Heng, Wei Xu, Vladimir Murzin,
	Lucas Wei, Kuninori Morimoto, Sascha Bischoff, Yicong Yang,
	Yeoreum Yun, linux-arm-kernel, linux-doc, linux-kernel, kvmarm
In-Reply-To: <87mrvy5640.wl-maz@kernel.org>

Marc Zyngier <maz@kernel.org> writes:

> Hi Scott,
>
> On Fri, 10 Jul 2026 23:21:28 +0100,
> D Scott Phillips <scott@os.amperecomputing.com> wrote:
>> 
>> On AmpereOne, deactivating a physical interrupt through ICC_DIR_EL1 or
>> ICC_EOIRx_EL1 (depending on EOImode) which is not active, but is the
>> highest priority pending interrupt causes the cpu to lose the interrupt
>> pending state and also prevents the delivery of future interrupts.
>>
>> Work around this in the vgic, avoiding the cpu issue.
>
> Thanks for getting to the bottom of this.
>
>> 
>> Signed-off-by: D Scott Phillips <scott@os.amperecomputing.com>
>> ---
>> 
>> Hi Marc, we've tracked down the nested virt hang reported
>> previously[1] to a cpu erratum in AmpereOne[2].
>> 
>> Here I'm just sort of parroting the change you had posted for
>> debugging. I'm not familiar with the vgic logic well enough to know if
>> this change is sufficient and doesn't have some unintended
>> consequences. I guess read this more are as "I've tested this and I'm
>> not seeing it hang now."
>>
>> Sorry for sending this half-baked, I didn't want to further delay the
>> errata details on my ongoing vgic education. I'm happy to take any
>> advice you can give, otherwise I'll continue familiarizing myself and
>> will hopefully later have a patch which I can actually claim I think is
>> correct.
>
> No worries.
>
> To be perfectly clear, what I posted at [1] *is* a bug-fix. A very
> minor one. Nothing wrong should come as a result, except when it does,
> such as in your case.
>
> The core reason why this happens is that the L2 will have EOI'd its
> timer, and that the HW bit set in the LR will have propagated the
> deactivation all the way to the HW redistributor. Then L1 takes over,
> and needs to reconcile the LR state with its own, namely its view of
> the active state.
>
> The issue here is that when dealing with a nested vgic (the state
> contained in the LRs is for L2, not L1), the deactivation process
> doesn't need to involve the HW again -- this has already be dealt
> with, and results in the double deactivation I mentioned in my email.

Ah ok, thanks, I think I get it.

>> 
>> [1]: https://lore.kernel.org/linux-arm-kernel/87ecjybz30.wl-maz@kernel.org/
>> 
>> [2]: https://amperecomputing.com/products/developer-errata
>> 
>> The updates with AC03_CPU_57 and AC04_CPU_29 have not yet been
>> published at the time I'm writing this. They should be coming
>> soon. I've reproduced the full entries from those two coming documents
>> collapsed together below:
>> 
>> | {AC03_CPU_57, AC04_CPU_29}: Deactivation of the non-active, highest
>> | priority pending interrupt prevents further interrupt delivery.
>> |
>> | Functional Unit: CPU
>> |
>> | Category: 4
>> |
>> | Affected Version(s): AmpereOne AC03 A0, AmpereOne AC03 B0
>> | Affected Version(s): AmpereOne AC04 A0, AmpereOne AC04_1 A0
>> |
>> | Fixed Version(s): Open
>> |
>> | Overview:
>> |
>> | If software directly deactivates a physical interrupt which is not
>> | in the active state, and the interrupt is also currently the highest
>> | priority pending interrupt, then interrupt delivery will cease on
>> | that PE. Deactivation can happen either through ICC_EOIRx_EL1 if
>> | ICC_CTLR_EL1.EOIMode==0, or through ICC_DIR_EL1 if
>> | ICC_CTLR_EL1.EOIMode==1. Deactivation of virtual interrupts that are
>> | redirected through ICV_ registers will not cause this issue, even
>> | when the virtual interrupt deactivation triggers a physical
>> | interrupt deactivation through ICH_LR<n>_EL2.HW=1.
>
> OK, that's pretty good news. Can I safely assume that your HW doesn't
> support VLPIs/VSGIs in any form (no GICv4+)?

AmpereOne AC04 does have gicv4.1 with vlpis/vsgis. Those take a
different enough path in the core that a deactivation of a pending
vlpi/vsgi won't cause the issue. The wording about "physical interrupt"
is meant to exclude vlpis/vsgis, sorry that it didn't come out clearly.

>> |
>> | This has been observed with Nested Virtualization starting with
>> | Linux-KVM v6.19.
>> |
>> | Impact:
>> |
>> | Physical interrupts will not be delivered after the deactivation of
>> | the non-active, highest priority pending interrupt. A core may
>> | appear to be hung.
>> |
>> | Workaround:
>> |
>> | Software must only deactivate interrupts which are currently active
>> 
>> 
>>  Documentation/arch/arm64/silicon-errata.rst |  4 ++++
>>  arch/arm64/Kconfig                          | 17 +++++++++++++++++
>>  arch/arm64/kernel/cpu_errata.c              | 15 +++++++++++++++
>>  arch/arm64/kvm/vgic/vgic-v3.c               |  4 +++-
>>  arch/arm64/tools/cpucaps                    |  1 +
>>  5 files changed, 40 insertions(+), 1 deletion(-)
>> 
>> diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
>> index 014aa1c215a16..89130404ce572 100644
>> --- a/Documentation/arch/arm64/silicon-errata.rst
>> +++ b/Documentation/arch/arm64/silicon-errata.rst
>> @@ -55,10 +55,14 @@ stable kernels.
>>  +----------------+-----------------+-----------------+-----------------------------+
>>  | Ampere         | AmpereOne       | AC03_CPU_38     | AMPERE_ERRATUM_AC03_CPU_38  |
>>  +----------------+-----------------+-----------------+-----------------------------+
>> +| Ampere         | AmpereOne       | AC03_CPU_57     | AMPERE_ERRATUM_AC03_CPU_57  |
>> ++----------------+-----------------+-----------------+-----------------------------+
>>  | Ampere         | AmpereOne AC04  | AC04_CPU_10     | AMPERE_ERRATUM_AC03_CPU_38  |
>>  +----------------+-----------------+-----------------+-----------------------------+
>>  | Ampere         | AmpereOne AC04  | AC04_CPU_23     | AMPERE_ERRATUM_AC04_CPU_23  |
>>  +----------------+-----------------+-----------------+-----------------------------+
>> +| Ampere         | AmpereOne AC04  | AC04_CPU_29     | AMPERE_ERRATUM_AC03_CPU_57  |
>> ++----------------+-----------------+-----------------+-----------------------------+
>>  +----------------+-----------------+-----------------+-----------------------------+
>>  | ARM            | Cortex-A510     | #2457168        | ARM64_ERRATUM_2457168       |
>>  +----------------+-----------------+-----------------+-----------------------------+
>> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> index b3afe0688919b..ee5421283d8df 100644
>> --- a/arch/arm64/Kconfig
>> +++ b/arch/arm64/Kconfig
>> @@ -436,6 +436,23 @@ config AMPERE_ERRATUM_AC03_CPU_38
>>  
>>  	  If unsure, say Y.
>>  
>> +config AMPERE_ERRATUM_AC03_CPU_57
>> +	bool "AmpereOne: AC03_CPU_57: Deactivation of the non-active, highest priority pending interrupt prevents further interrupt delivery."
>> +	default y
>> +	help
>> +	  This option adds an alternative code sequence to work around Ampere
>> +	  errata AC03_CPU_57 and AC04_CPU_29 on AmpereOne.
>> +
>> +	  Deactivating a physical interrupt through ICC_DIR_EL1 or
>> +	  ICC_EOIR1_EL1 (depending on EOImode) which is not active, but is the
>> +	  highest priority pending interrupt causes the cpu to lose the
>> +	  interrupt pending state and also prevents the delivery of future
>> +	  interrupts.
>> +
>> +	  The workaround is for KVM to not deactivate interrupts for nested vgics.
>> +
>> +	  If unsure, say Y.
>> +
>>  config AMPERE_ERRATUM_AC04_CPU_23
>>          bool "AmpereOne: AC04_CPU_23:  Failure to synchronize writes to HCR_EL2 may corrupt address translations."
>>  	default y
>> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
>> index 1995e1198648e..9b03dccd55e09 100644
>> --- a/arch/arm64/kernel/cpu_errata.c
>> +++ b/arch/arm64/kernel/cpu_errata.c
>> @@ -631,6 +631,14 @@ static const struct midr_range erratum_ac03_cpu_38_list[] = {
>>  };
>>  #endif
>>  
>> +#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_57
>> +static const struct midr_range erratum_ac03_cpu_57_list[] = {
>> +	MIDR_ALL_VERSIONS(MIDR_AMPERE1),
>> +	MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
>> +	{},
>> +};
>> +#endif
>> +
>>  #ifdef CONFIG_AMPERE_ERRATUM_AC04_CPU_23
>>  static const struct midr_range erratum_ac04_cpu_23_list[] = {
>>  	MIDR_ALL_VERSIONS(MIDR_AMPERE1A),
>> @@ -987,6 +995,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>>  		ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_38_list),
>>  	},
>>  #endif
>> +#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_57
>> +	{
>> +		.desc = "AmpereOne erratum AC03_CPU_57",
>> +		.capability = ARM64_WORKAROUND_AMPERE_AC03_CPU_57,
>> +		ERRATA_MIDR_RANGE_LIST(erratum_ac03_cpu_57_list),
>> +	},
>> +#endif
>>  #ifdef CONFIG_AMPERE_ERRATUM_AC04_CPU_23
>>  	{
>>  		.desc = "AmpereOne erratum AC04_CPU_23",
>> diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
>> index 9e841e7afd4a7..8f1d10872360c 100644
>> --- a/arch/arm64/kvm/vgic/vgic-v3.c
>> +++ b/arch/arm64/kvm/vgic/vgic-v3.c
>> @@ -275,7 +275,9 @@ void vgic_v3_deactivate(struct kvm_vcpu *vcpu, u64 val)
>>  		lr = vgic_v3_compute_lr(vcpu, irq) & ~ICH_LR_ACTIVE_BIT;
>>  	}
>>  
>> -	if (lr & ICH_LR_HW)
>> +	if ((lr & ICH_LR_HW) &&
>> +	    !(cpus_have_final_cap(ARM64_WORKAROUND_AMPERE_AC03_CPU_57) &&
>> +	      vgic_state_is_nested(vcpu)))
>>  		vgic_v3_deactivate_phys(FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
>
> I think this is slightly overkill. The hack I posted should be enough,
> and we can replace all the capability business with a simple comment
> referencing the errata numbers and the entries in silicon-errata.rst.
>
> Use the information provided above to beef up the commit message and
> stick:
>
> Cc: stable@vger.kernel.org
> Fixes: 6dd333c8942b2 ("KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive")
>
> so that we know how far this needs to be backported.

Thanks, will do

^ permalink raw reply

* Re: [PATCH v5 0/3] x86,fs/resctrl,arm_mpam: Factor MBA parse-time conversion to be per-arch
From: Moger, Babu @ 2026-07-14 22:48 UTC (permalink / raw)
  To: Reinette Chatre, Ben Horgan, bp, x86
  Cc: james.morse, fenghuay, linux-kernel, linux-arm-kernel, tglx,
	mingo, dave.hansen, hpa, corbet, linux-doc, dave.martin
In-Reply-To: <165e7636-d7e9-4d16-aad1-657b4a9698d0@intel.com>

Ran few tests on the series. Everything looks good.

Tested-by: Babu Moger <babu.moger@amd.com>


On 7/14/2026 12:45 PM, Reinette Chatre wrote:
> Dear x86 maintainers,
> 
> Could you please consider this series for inclusion? It applies cleanly on top
> of x86/cache with HEAD at
> 	 2566b5cd6a27 ("fs/resctrl: Fix UAF from worker threads when domains are removed")
> 
> Please note that this is the first instance of a series that touches resctrl fs, x86, and
> Arm. Since this is a resctrl fs API change these patches should stay together. You will
> find in Ben's message below that patch routing via tip is supported by Arm.
> 
> Thank you very much
> 
> Reinette
> 
> On 7/9/26 2:31 AM, Ben Horgan wrote:
>> This version fixes a couple of non-functional mistakes in v4 pointed out by Reinette.
>>
>> The patches should stay together so please could this all go via tip.
>>
>> Changelogs in patches.
>>
>>  From cover letter of v3:
>>
>> This is a new version of Dave Martin's patch [1] to delegate rounding of
>> bandwidth control user values to the arch code. As there is now more than one
>> architecture using resctrl, I split the original patch into two, a core resctrl
>> patch and an x86 patch, and added an MPAM patch. Please let me know if the patch
>> break down and ordering is sensible and whether the pattern should be followed
>> for any future similar changes.
>>
>> This does have a user visible effect on MB schema when using MPAM hardware
>> with 'bandwidth_gran' greater than 1. I'm not sure if MPAM hardware with such
>> coarse controls exists in the wild but it is spec compliant and I've tested it
>> on a model.
>>
>> [1] https://lore.kernel.org/lkml/20251031154225.14799-1-Dave.Martin@arm.com/
>>
>> v3: https://lore.kernel.org/lkml/20260515140612.1205251-1-ben.horgan@arm.com/
>> v4: https://lore.kernel.org/lkml/20260706160639.2136674-1-ben.horgan@arm.com/
>>
>> Based on v7.2-rc2
>>
>> Ben Horgan (1):
>>    arm_mpam: resctrl: Add pass-through resctrl_arch_preconvert_bw()
>>
>> Dave Martin (2):
>>    x86,fs/resctrl: Add resctrl_arch_preconvert_bw()
>>    fs/resctrl: Factor MBA parse-time conversion to be per-arch
>>
>>   Documentation/filesystems/resctrl.rst     | 17 +++++++++--------
>>   arch/x86/kernel/cpu/resctrl/ctrlmondata.c |  6 ++++++
>>   drivers/resctrl/mpam_resctrl.c            |  5 +++++
>>   fs/resctrl/ctrlmondata.c                  |  6 +++---
>>   include/linux/resctrl.h                   | 19 +++++++++++++++++++
>>   5 files changed, 42 insertions(+), 11 deletions(-)
>>
> 
> 


^ permalink raw reply

* [PATCH] docs: pt_BR: process: Translate programming-language
From: Abel Philippe @ 2026-07-14 22:23 UTC (permalink / raw)
  To: danielmaraboo; +Cc: linux-doc, corbet, Abel Philippe

Translate the programming language documentation into Brazilian Portuguese.

Signed-off-by: Abel Philippe <le590616@gmail.com>
---
 pt_BR/process/programming-language.rst | 56 ++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
 create mode 100644 pt_BR/process/programming-language.rst

diff --git a/pt_BR/process/programming-language.rst b/pt_BR/process/programming-language.rst
new file mode 100644
index 000000000000..740e03cddff2
--- /dev/null
+++ b/pt_BR/process/programming-language.rst
@@ -0,0 +1,56 @@
+Linguagem de programação 
+========================
+
+O kernel Linux é escrito na linguagem de programação C [c-language]_.
+Mais precisamente, ele é normalmente compilado com ``gcc`` [gcc]_
+sob ``-std=gnu11`` [gcc-c-dialect-options]_, o dialeto GNU da ISO C11.
+O compilador ``clang`` [clang]_ também é suportado; consulte a documentação em
+:ref:`Building Linux with Clang/LLVM <kbuild_llvm>`.
+
+Esse dialeto contém diversas extensões da linguagem [gnu-extensions]_,
+e muitas delas são utilizadas rotineiramente no kernel.
+
+Atributos
+---------
+
+Uma das extensões mais comuns utilizadas em todo o kernel são os atributos
+[gcc-attribute-syntax]_. Os atributos permitem introduzir
+semânticas definidas pela implementação em entidades da linguagem (como variáveis,
+funções ou tipos) sem a necessidade de realizar mudanças sintáticas
+significativas na linguagem (por exemplo, adicionando uma nova palavra-chave) [n2049]_.
+
+Em alguns casos, os atributos são opcionais (isto é, um compilador que não os
+suporte ainda deve produzir código correto, mesmo que ele seja mais lento ou
+não execute tantas verificações e diagnósticos durante a compilação).
+
+O kernel define pseudopalavras-chave (por exemplo, ``__pure``) em vez de usar
+diretamente a sintaxe de atributos do GNU (por exemplo, ``__attribute__((__pure__))``)
+para detectar quais deles podem ser utilizados e/ou para encurtar o código.
+
+Por favor, consulte ``include/linux/compiler_attributes.h`` para mais informações.
+
+Rust
+----
+
+O kernel tem suporte para a linguagem de programação Rust.
+[rust-language]_ sob ``CONFIG_RUST``. É compilado com o ``rustc`` [rustc]_ ``rustc`` [rustc]_
+sob ``--edition=2021`` [rust-editions]_. As edições são uma maneira de introduzir
+pequenas alterações na linguagem que não são retrocompatíveis.
+
+Além disso, alguns recursos instáveis ​​[rust-unstable-features]_ são utilizados no
+kernel. Recursos instáveis ​​podem sofrer alterações no futuro; portanto, é um
+objetivo importante chegar a um ponto em que apenas recursos estáveis ​​sejam utilizados.
+
+Consulte ``Documentation/rust/index.rst`` para obter mais informações.
+
+.. [c-language] http://www.open-std.org/jtc1/sc22/wg14/www/standards
+.. [gcc] https://gcc.gnu.org
+.. [clang] https://clang.llvm.org
+.. [gcc-c-dialect-options] https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html
+.. [gnu-extensions] https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html
+.. [gcc-attribute-syntax] https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+.. [n2049] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2049.pdf
+.. [rust-language] https://www.rust-lang.org
+.. [rustc] https://doc.rust-lang.org/rustc/
+.. [rust-editions] https://doc.rust-lang.org/edition-guide/editions/
+.. [rust-unstable-features] https://github.com/Rust-for-Linux/linux/issues/2
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
From: Stanislav Kinsburskii @ 2026-07-14 22:21 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178406760622.1106335.2379450382728057793.stgit@skinsburskii>

The timeout passed to hmm_range_fault_unlocked_timeout() is a relative
retry budget for HMM's internal mmu-notifier retry loop. drm_gpusvm was
still keeping an absolute deadline around the outer driver retry logic
and passing the remaining time into HMM.

Pass HMM_RANGE_DEFAULT_TIMEOUT directly to
hmm_range_fault_unlocked_timeout() on each HMM fault attempt instead.
If HMM succeeds but the later drm_gpusvm-side mmu_interval_read_retry()
check observes an invalidation, retry with a fresh HMM retry budget.

This keeps the timeout focused on repeated notifier retries inside HMM,
while avoiding an outer deadline that also accounts unrelated driver-side
work after HMM has made progress.

Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
 drivers/gpu/drm/drm_gpusvm.c |   21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index b8f2dd9982f5..76e8a0028c7f 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -852,8 +852,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
 		.end = end,
 		.dev_private_owner = dev_private_owner,
 	};
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED, new_state;
 	unsigned long *pfns;
 	unsigned long npages = npages_in_range(start, end);
@@ -867,8 +866,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
 	hmm_range.hmm_pfns = pfns;
 
 retry:
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-					       max(timeout - jiffies, 1L));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 	if (err)
 		goto err_free;
 
@@ -1459,8 +1457,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 		.dev_private_owner = ctx->device_private_page_owner,
 	};
 	void *zdd;
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	unsigned long i, j;
 	unsigned long npages = npages_in_range(pages_start, pages_end);
 	unsigned long num_dma_mapped;
@@ -1478,9 +1475,6 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 		return -EINVAL;
 
 retry:
-	if (time_after(jiffies, timeout))
-		return -EBUSY;
-
 	hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
 	if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
 		goto set_seqno;
@@ -1495,8 +1489,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 	}
 
 	hmm_range.hmm_pfns = pfns;
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-				max_t(long, timeout - jiffies, 1));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 	mmput(mm);
 	if (err)
 		goto err_free;
@@ -1718,8 +1711,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
 		.end = drm_gpusvm_range_end(range),
 		.dev_private_owner = NULL,
 	};
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	unsigned long *pfns;
 	unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
 					       drm_gpusvm_range_end(range));
@@ -1734,8 +1726,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
 		return -ENOMEM;
 
 	hmm_range.hmm_pfns = pfns;
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-				max_t(long, timeout - jiffies, 1));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 
 	kvfree(pfns);
 	mmput(mm);



^ permalink raw reply related

* [PATCH v2 3/4] fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
From: Stanislav Kinsburskii @ 2026-07-14 22:21 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178406760622.1106335.2379450382728057793.stgit@skinsburskii>

aie2_populate_range() now uses hmm_range_fault_unlocked_timeout() to let
HMM own mmap_lock acquisition and retry handling while populating an
invalid user mapping. The timeout passed to that helper is a relative
HMM retry budget, not an absolute deadline.

Pass HMM_RANGE_DEFAULT_TIMEOUT directly to the HMM helper instead of
computing the remaining time from a local absolute deadline. The broader
command submission path still keeps its existing timeout around repeated
range population attempts, while each HMM fault attempt receives a fresh
retry budget for HMM's internal mmu-notifier retries.

Keep the existing driver-visible timeout errno by translating -EBUSY
from hmm_range_fault_unlocked_timeout() to -ETIME on return.

Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
 drivers/accel/amdxdna/aie2_ctx.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 548ba4315554..21f2817751f9 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -1037,7 +1037,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
 	bool found;
 	int ret;
 
-	timeout = jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 again:
 	found = false;
 	down_write(&xdna->notifier_lock);
@@ -1062,13 +1062,9 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
 		return -EFAULT;
 	}
 
-	ret = hmm_range_fault_unlocked_timeout(&mapp->range,
-			max_t(long, timeout - jiffies, 1));
-	if (ret) {
-		if (ret == -EBUSY)
-			ret = -ETIME;
+	ret = hmm_range_fault_unlocked_timeout(&mapp->range, timeout);
+	if (ret)
 		goto put_mm;
-	}
 
 	down_write(&xdna->notifier_lock);
 	if (mmu_interval_read_retry(&mapp->notifier, mapp->range.notifier_seq)) {
@@ -1086,7 +1082,7 @@ static int aie2_populate_range(struct amdxdna_gem_obj *abo)
 put_mm:
 	amdxdna_umap_put(mapp);
 	mmput(mm);
-	return ret;
+	return ret == -EBUSY ? -ETIME : ret;
 }
 
 int aie2_cmd_submit(struct amdxdna_hwctx *hwctx, struct amdxdna_sched_job *job, u64 *seq)



^ permalink raw reply related

* [PATCH v2 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
From: Stanislav Kinsburskii @ 2026-07-14 22:21 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178406760622.1106335.2379450382728057793.stgit@skinsburskii>

nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
the HMM fault path. Pass the remaining SVM fault timeout into HMM as a
positive relative timeout instead of open-coding the HMM retry loop in
nouveau.

Keep the outer absolute timeout around nouveau's
mmu_interval_read_retry() loop. HMM's timeout only bounds retries while
HMM is walking and faulting the range. Once HMM returns successfully, a
continuous stream of mmu-notifier invalidations can still make
mmu_interval_read_retry() restart the operation. This path runs from the
GPU fault worker, so fatal signals for the faulting userspace task cannot
be relied on to break that outer loop.

Use time_after_eq() before the HMM call so the remaining timeout passed
to HMM is always positive. This preserves the old timeout behavior at the
expiry boundary and avoids passing 0, which means retry indefinitely, to
hmm_range_fault_unlocked_timeout().

Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
 drivers/gpu/drm/nouveau/nouveau_svm.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 4cfb6eb7c771..58735446d783 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -678,14 +678,20 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
 	range.end = notifier->notifier.interval_tree.last + 1;
 
 	while (true) {
-		if (time_after(jiffies, timeout)) {
+		long remaining = timeout - jiffies;
+
+		/*
+		 * The HMM timeout only bounds retries while HMM is walking and
+		 * faulting the range. This fault is handled by a kernel worker,
+		 * so fatal signals from the faulting process cannot stop an
+		 * endless stream of invalidations here.
+		 */
+		if (time_after_eq(jiffies, timeout)) {
 			ret = -EBUSY;
 			goto out;
 		}
 
-		ret = hmm_range_fault_unlocked_timeout(&range,
-						       max(timeout - jiffies,
-							   1L));
+		ret = hmm_range_fault_unlocked_timeout(&range, remaining);
 		if (ret)
 			goto out;
 



^ permalink raw reply related

* [PATCH v2 1/4] fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support
From: Stanislav Kinsburskii @ 2026-07-14 22:21 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178406760622.1106335.2379450382728057793.stgit@skinsburskii>

The hmm_range_fault_unlocked_timeout() example checks for a concurrent
mmu_interval_notifier invalidation after the HMM fault has succeeded.
The sequence number used for that check is stored in range->notifier_seq
by hmm_range_fault_unlocked_timeout(), so the retry check should use the
same notifier stored in range as well.

Update the example to pass range.notifier to mmu_interval_read_retry(),
and spell out that the retry check uses the notifier and sequence number
stored in range by the HMM fault helper. This makes the relationship
between the HMM walk and the later invalidation check explicit.

Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
 Documentation/mm/hmm.rst |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/Documentation/mm/hmm.rst b/Documentation/mm/hmm.rst
index 5c88d2cf0818..fc1b8dc19825 100644
--- a/Documentation/mm/hmm.rst
+++ b/Documentation/mm/hmm.rst
@@ -206,7 +206,7 @@ The usage pattern is::
           goto out_put;
 
       take_lock(driver->update);
-      if (mmu_interval_read_retry(&interval_sub, range.notifier_seq)) {
+      if (mmu_interval_read_retry(range.notifier, range.notifier_seq)) {
           release_lock(driver->update);
           goto again;
       }
@@ -225,7 +225,8 @@ The usage pattern is::
 The driver->update lock is the same lock that the driver takes inside its
 invalidate() callback. That lock must be held before calling
 mmu_interval_read_retry() to avoid any race with a concurrent CPU page table
-update.
+update. The retry check must use the same notifier and sequence number stored
+in ``range`` by ``hmm_range_fault_unlocked_timeout()``.
 
 Holding the mmap lock across HMM faults
 =======================================



^ permalink raw reply related

* [PATCH v2 0/4] mm/hmm: Clarify notifier retry state and scope HMM timeouts
From: Stanislav Kinsburskii @ 2026-07-14 22:21 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma

This small fixup series applies on top of:

  [PATCH v8 0/8] mm/hmm: Add mmap lock-drop support for userfaultfd-backed mappings

The first patch updates the HMM documentation example to make the
mmu_interval_read_retry() state explicit: callers should use the notifier and
notifier_seq stored in the same hmm_range that was passed to
hmm_range_fault_unlocked_timeout().

The remaining patches adjust nouveau, amdxdna, and drm_gpusvm users so the
timeout passed to hmm_range_fault_unlocked_timeout() is treated as a relative
HMM retry budget. These callers no longer keep an absolute deadline around
their outer driver retry loops or pass a computed remaining time into HMM.

This keeps the timeout scoped to HMM's internal mmu-notifier retry handling. If
HMM succeeds and the driver later observes an invalidation through
mmu_interval_read_retry(), the driver retries the operation with a fresh HMM
retry budget.

Changes in v2:
  - Kept the nouveau outer absolute timeout around the
    mmu_interval_read_retry() loop. hmm_range_fault_unlocked_timeout() only
    bounds HMM’s internal retries, while nouveau faults are handled from a GPU
    fault worker, so userspace fatal signals cannot break an endless stream of
    invalidations there.
  - Updated nouveau to use time_after_eq() before calling HMM, so the remaining
    timeout passed to hmm_range_fault_unlocked_timeout() is always positive and
    never 0, which would mean retry indefinitely.
  - Updated the nouveau fixup commit message to explain the worker-thread
    timeout issue and the time_after_eq() boundary behavior.
  - Fixed the amdxdna fixup commit message. It now describes
    aie2_populate_range() correctly instead of carrying stale nouveau prose,
    and notes that command submission still keeps its broader timeout while HMM
    gets a fresh relative retry budget.


---

Stanislav Kinsburskii (4):
      fixup! mm/hmm: add hmm_range_fault_unlocked_timeout() for mmap lock-drop support
      fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
      fixup! accel/amdxdna: use hmm_range_fault_unlocked_timeout() for range population
      fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults


 Documentation/mm/hmm.rst              |    5 +++--
 drivers/accel/amdxdna/aie2_ctx.c      |   12 ++++--------
 drivers/gpu/drm/drm_gpusvm.c          |   21 ++++++---------------
 drivers/gpu/drm/nouveau/nouveau_svm.c |   14 ++++++++++----
 4 files changed, 23 insertions(+), 29 deletions(-)


^ permalink raw reply

* Re: [RFC PATCH v4 2/3] trace: integrate stackmap into ftrace stack recording path
From: Steven Rostedt @ 2026-07-14 21:53 UTC (permalink / raw)
  To: Li Pengfei
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Mark Rutland,
	Jonathan Corbet, Shuah Khan, linux-kernel, linux-trace-kernel,
	linux-doc, linux-kselftest, lipengfei28, zhangbo56
In-Reply-To: <20260616064119.438063-3-lipengfei28@xiaomi.com>

On Tue, 16 Jun 2026 14:41:18 +0800
Li Pengfei <ljdlns1987@gmail.com> wrote:

>  int set_tracer_flag(struct trace_array *tr, u64 mask, int enabled)
>  {
>  	switch (mask) {
> @@ -3993,6 +4091,33 @@ int set_tracer_flag(struct trace_array *tr, u64 mask, int enabled)
>  	if (!!(tr->trace_flags & mask) == !!enabled)
>  		return 0;
>  
> +#ifdef CONFIG_FTRACE_STACKMAP
> +	/*
> +	 * STACKMAP is intentionally global-instance-only: the dedup map,
> +	 * its tracefs files (stack_map / stack_map_stat / stack_map_bin)
> +	 * and the lifetime/reset semantics are tied to the global trace
> +	 * array. options/stackmap is hidden on secondary instances via
> +	 * TOP_LEVEL_TRACE_FLAGS, but writes still reach set_tracer_flag()
> +	 * through the aggregate trace_options file. Reject the enable on
> +	 * a secondary instance so it cannot be silently accepted and then
> +	 * become a no-op in the hot path (where tr->stackmap is NULL and
> +	 * the code falls back to a full stack trace).
> +	 *
> +	 * On the global instance, allow the enable while init is still
> +	 * pending (boot-time trace_options=stackmap is applied before the
> +	 * tracefs init work creates the map; the hot path falls back
> +	 * until the map is published). Only reject once init has
> +	 * permanently failed, so options/stackmap never reports an
> +	 * enabled no-op. READ_ONCE() suffices: this only inspects the
> +	 * init state, it does not dereference the map (the hot path uses
> +	 * smp_load_acquire(&tr->stackmap) for that).
> +	 */
> +	if (mask == TRACE_ITER(STACKMAP) && enabled &&
> +	    (tr != &global_trace ||
> +	     READ_ONCE(stackmap_init_state) == STACKMAP_INIT_FAILED))
> +		return -EINVAL;
> +#endif
> +
>  	/* Give the tracer a chance to approve the change */
>  	if (tr->current_trace->flag_changed)
>  		if (tr->current_trace->flag_changed(tr, mask, !!enabled))
> @@ -9222,6 +9347,91 @@ static __init void tracer_init_tracefs_work_func(struct work_struct *work)
>  			NULL, &tracing_dyn_info_fops);
>  #endif
>  
> +#ifdef CONFIG_FTRACE_STACKMAP
> +	{
> +		struct ftrace_stackmap *smap;
> +		struct dentry *map_file;
> +
> +		smap = ftrace_stackmap_create(&global_trace);
> +		if (!IS_ERR(smap)) {
> +			/*
> +			 * Failure-atomic init: stack_map is the single
> +			 * required tracefs file (it doubles as the reset
> +			 * interface and the human-readable resolver). If
> +			 * we cannot create it, the hot path must not be
> +			 * able to emit <stack_id N> events that no one can
> +			 * resolve or clear, so refuse to publish the map
> +			 * and tear it down.
> +			 *
> +			 * Create stack_map BEFORE smp_store_release() so an
> +			 * observed non-NULL global_trace.stackmap implies
> +			 * its resolver/reset file exists.
> +			 */
> +			map_file = trace_create_file("stack_map",
> +						     TRACE_MODE_WRITE, NULL,
> +						     smap,
> +						     &ftrace_stackmap_fops);
> +			if (!map_file) {
> +				pr_warn("ftrace stackmap init: stack_map create failed, dedup disabled\n");
> +				ftrace_stackmap_destroy(smap);
> +				/*
> +				 * Permanent failure. Record it and clear a
> +				 * STACKMAP flag that a boot-time
> +				 * trace_options=stackmap may have set, so
> +				 * options/stackmap does not report an
> +				 * enabled no-op and later userspace enables
> +				 * return -EINVAL.
> +				 */
> +				WRITE_ONCE(stackmap_init_state,
> +					   STACKMAP_INIT_FAILED);
> +				global_trace.trace_flags &=
> +					~TRACE_ITER(STACKMAP);

80 columns is no longer a hard requirement. 100 is more the default, so the
above should be:

				WRITE_ONCE(stackmap_init_state, STACKMAP_INIT_FAILED);
				global_trace.trace_flags &= ~TRACE_ITER(STACKMAP);



> +			} else {
> +				/*
> +				 * smp_store_release pairs with the
> +				 * smp_load_acquire() in
> +				 * __ftrace_trace_stack(). Publishing only
> +				 * after the required file exists keeps
> +				 * "smap visible" => "resolver/reset
> +				 * available".
> +				 */

> +				smp_store_release(&global_trace.stackmap,
> +						  smap);
> +				WRITE_ONCE(stackmap_init_state,
> +					   STACKMAP_INIT_DONE);

Same with the above two.

> +				/*
> +				 * stat and bin are auxiliary observability
> +				 * surfaces. If they fail to be created we
> +				 * keep dedup enabled (the kernel side still
> +				 * works, and stack_map alone is enough to
> +				 * resolve and reset); trace_create_file()
> +				 * already pr_warn()s on failure.
> +				 */
> +				trace_create_file("stack_map_stat",
> +						  TRACE_MODE_READ, NULL,
> +						  smap,
> +						  &ftrace_stackmap_stat_fops);
> +				trace_create_file("stack_map_bin",
> +						  TRACE_MODE_READ, NULL,
> +						  smap,
> +						  &ftrace_stackmap_bin_fops);
> +			}

-- Steve

^ permalink raw reply

* Re: [PATCH v3 6/6] Documentation/kernel-parameters: add/update printk_delay/boot_delay
From: Steven Rostedt @ 2026-07-14 21:51 UTC (permalink / raw)
  To: Andrew Murray
  Cc: Petr Mladek, John Ogness, Sergey Senozhatsky, Jonathan Corbet,
	Shuah Khan, Russell King, Florian Fainelli,
	Broadcom internal kernel review list, Ray Jui, Scott Branden,
	Andrew Morton, Greg Kroah-Hartman, Sebastian Andrzej Siewior,
	Clark Williams, linux-kernel, linux-doc, linux-arm-kernel,
	linux-rpi-kernel, linux-rt-devel
In-Reply-To: <20260712-printkcleanup-v3-6-574547b8f71b@thegoodpenguin.co.uk>

On Sun, 12 Jul 2026 11:20:37 +0100
Andrew Murray <amurray@thegoodpenguin.co.uk> wrote:

> diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
> index 2884103b93bca7b76cd3a93946276074cf62d0a1..1118feda87b1b04543b1da0bd52c090b1fddaeac 100644
> --- a/Documentation/admin-guide/kernel-parameters.txt
> +++ b/Documentation/admin-guide/kernel-parameters.txt
> @@ -650,11 +650,19 @@ Kernel parameters
>  			See Documentation/block/cmdline-partition.rst
>  
>  	boot_delay=	[KNL,EARLY]
> -			Milliseconds to delay each printk during boot.
> -			Only works if GENERIC_CALIBRATE_DELAY is enabled,
> -			and you may also have to specify "lpj=".  Boot_delay
> -			values larger than 10 seconds (10000) are assumed
> -			erroneous and ignored.
> +			Milliseconds to delay each printk during and post boot.
> +			Boot time delays only work if GENERIC_CALIBRATE_DELAY
> +			is enabled.
> +
> +			Once booted the delay can be removed or adjusted via
> +			the printk_delay sysctl.
> +
> +			Please note that you may also have to specify "lpj=".
> +			Boot_delay values larger than 10 seconds (10000) are
> +			assumed erroneous and ignored.
> +
> +			This will soon be deprecated, please use printk_delay
> +			instead.
>  			Format: integer
>  
>  	bootconfig	[KNL,EARLY]
> @@ -5468,6 +5476,19 @@ Kernel parameters
>  	printk.time=	Show timing data prefixed to each printk message line
>  			Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
>  
> +	printk_delay=	[KNL,EARLY]
> +			Milliseconds to delay each printk during and post boot.
> +			Boot time delays only work if GENERIC_CALIBRATE_DELAY
> +			is enabled.
> +
> +			Once booted the delay can be removed or adjusted via
> +			the printk_delay sysctl.
> +
> +			Please note that you may also have to specify "lpj=".
> +			printk_delay values larger than 10 seconds (10000) are
> +			assumed erroneous and ignored.
> +			Format: integer
> +

The two parameters descriptions are identical. They should show something
different. Is it just that the "boot_delay" name is getting deprecated?

-- Steve

^ permalink raw reply

* Re: [PATCH] scripts/kernel-doc: Suggest possible names for excess descriptions
From: Randy Dunlap @ 2026-07-14 21:44 UTC (permalink / raw)
  To: Ryszard Knop, linux-doc
  Cc: Shuicheng Lin, Jani Nikula, linux-kernel, intel-xe
In-Reply-To: <20260714111208.323108-1-ryszard.knop@intel.com>

Hi,


On 7/14/26 4:12 AM, Ryszard Knop wrote:
> Since check_sections() now warns if a documentation tag member name is
> the same as defined in the struct, we can suggest names the checker
> knows, so that it's more obvious how to deal with the warning.
> 

Seems to work for me.

> Signed-off-by: Ryszard Knop <ryszard.knop@intel.com>
> ---
>  tools/lib/python/kdoc/kdoc_parser.py | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/lib/python/kdoc/kdoc_parser.py b/tools/lib/python/kdoc/kdoc_parser.py
> index 2dedda215c22..3f88095eab06 100644
> --- a/tools/lib/python/kdoc/kdoc_parser.py
> +++ b/tools/lib/python/kdoc/kdoc_parser.py
> @@ -558,6 +558,13 @@ class KernelDoc:
>                          self.push_parameter(ln, decl_type, param, dtype,
>                                              arg, declaration_name)
>  
> +    def get_suggestions_hint(self, decl_name, possible_names):
> +        suggestions = set(name for name in possible_names if decl_name in name)
> +        if not suggestions:
> +            return ""
> +
> +        return f"(did you mean one of: '{"', '".join(suggestions)}')"
> +
>      def check_sections(self, ln, decl_name, decl_type):
>          """
>          Check for errors inside sections, emitting warnings if not found
> @@ -566,12 +573,13 @@ class KernelDoc:
>          for section in self.entry.sections:
>              if section not in self.entry.parameterlist and \
>                 not known_sections.search(section):
> +                hint = self.get_suggestions_hint(section, self.entry.parameterlist)
>                  if decl_type == 'function':
>                      dname = f"{decl_type} parameter"
>                  else:
>                      dname = f"{decl_type} member"
>                  self.emit_msg(ln,
> -                              f"Excess {dname} '{section}' description in '{decl_name}'")
> +                              f"Excess {dname} '{section}' description in '{decl_name}' {hint}")

When 'hint' is empty, this statement and/or the similar one below
adds a trailing space to each of those lines.
Can you prevent that?  (yeah, it's just a nit)

>  
>          #
>          # Check that documented parameter names (from doc comments, including
> @@ -591,12 +599,13 @@ class KernelDoc:
>              if param_name in self.entry.parameterlist:
>                  continue
>  
> +            hint = self.get_suggestions_hint(param_name, self.entry.parameterlist)
>              if decl_type == 'function':
>                  dname = f"{decl_type} parameter"
>              else:
>                  dname = f"{decl_type} member"
>              self.emit_msg(ln,
> -                          f"Excess {dname} '{param_name}' description in '{decl_name}'")
> +                          f"Excess {dname} '{param_name}' description in '{decl_name}' {hint}")
>  
>      def check_return_section(self, ln, declaration_name, return_type):
>          """

Acked-by: Randy Dunlap <rdunlap@infradead.org>
Tested-by: Randy Dunlap <rdunlap@infradead.org>

thanks.
-- 
~Randy

^ permalink raw reply

* Re: [PATCH 2/4] fixup! drm/nouveau: use hmm_range_fault_unlocked_timeout() for SVM faults
From: Stanislav Kinsburskii @ 2026-07-14 21:33 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178406001808.1082778.17299764648397654220.stgit@skinsburskii>

On Tue, Jul 14, 2026 at 01:13:38PM -0700, Stanislav Kinsburskii wrote:
> nouveau_range_fault() now uses hmm_range_fault_unlocked_timeout() for
> the HMM fault path. The timeout passed to that helper is meant to bound
> HMM's internal mmu-notifier retry loop, not the whole nouveau retry loop
> around mmu_interval_read_retry().
> 
> Pass the full relative HMM_RANGE_DEFAULT_TIMEOUT value to
> hmm_range_fault_unlocked_timeout() on each attempt, and retry from the
> nouveau-side mmu_interval_read_retry() check with a fresh HMM retry
> budget. This lets HMM continue when it has made progress, while still
> preserving a timeout for repeated notifier invalidation retries inside
> one HMM fault attempt.
> 
> This also removes the open-coded absolute deadline and remaining-time
> calculation from nouveau_range_fault().
> 

Sashiko is right. I'll need to do it differently.
There will be a v2 of this series.

Thanks,
Stanislav


> Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
> ---
>  drivers/gpu/drm/nouveau/nouveau_svm.c |   30 ++++++++++--------------------
>  1 file changed, 10 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
> index 4cfb6eb7c771..b1415c2e49fc 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_svm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
> @@ -655,8 +655,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
>  			       unsigned long hmm_flags,
>  			       struct svm_notifier *notifier)
>  {
> -	unsigned long timeout =
> -		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
> +	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
>  	/* Have HMM fault pages within the fault window to the GPU. */
>  	unsigned long hmm_pfns[1];
>  	struct hmm_range range = {
> @@ -677,25 +676,16 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
>  	range.start = notifier->notifier.interval_tree.start;
>  	range.end = notifier->notifier.interval_tree.last + 1;
>  
> -	while (true) {
> -		if (time_after(jiffies, timeout)) {
> -			ret = -EBUSY;
> -			goto out;
> -		}
> -
> -		ret = hmm_range_fault_unlocked_timeout(&range,
> -						       max(timeout - jiffies,
> -							   1L));
> -		if (ret)
> -			goto out;
> +again:
> +	ret = hmm_range_fault_unlocked_timeout(&range, timeout);
> +	if (ret)
> +		goto out;
>  
> -		mutex_lock(&svmm->mutex);
> -		if (mmu_interval_read_retry(range.notifier,
> -					    range.notifier_seq)) {
> -			mutex_unlock(&svmm->mutex);
> -			continue;
> -		}
> -		break;
> +	mutex_lock(&svmm->mutex);
> +	if (mmu_interval_read_retry(range.notifier,
> +				    range.notifier_seq)) {
> +		mutex_unlock(&svmm->mutex);
> +		goto again;
>  	}
>  
>  	nouveau_hmm_convert_pfn(drm, &range, args);
> 
> 

^ permalink raw reply

* Re: [RFC PATCH 08/13] mm/kwatch: add hardware breakpoint backend
From: Steven Rostedt @ 2026-07-14 21:14 UTC (permalink / raw)
  To: Jinchao Wang
  Cc: Andrew Morton, Peter Zijlstra, Thomas Gleixner, Masami Hiramatsu,
	Ingo Molnar, Borislav Petkov, Dave Hansen, H . Peter Anvin, x86,
	Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
	Mathieu Desnoyers, David Hildenbrand, Jonathan Corbet,
	Matthew Wilcox, linux-kernel, linux-mm, linux-trace-kernel,
	linux-perf-users, linux-doc
In-Reply-To: <20260714183206.12688-1-wangjinchao600@gmail.com>

On Wed, 15 Jul 2026 02:32:06 +0800
Jinchao Wang <wangjinchao600@gmail.com> wrote:

> --- /dev/null
> +++ b/include/trace/events/kwatch.h
> @@ -0,0 +1,57 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM kwatch
> +
> +#if !defined(_TRACE_KWATCH_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TRACE_KWATCH_H
> +
> +#include <linux/tracepoint.h>
> +#include <linux/ptrace.h>
> +
> +#define KWATCH_STACK_DEPTH 8
> +
> +struct trace_seq;
> +const char *kwatch_trace_print_stack(struct trace_seq *p,
> +				     const unsigned long *stack,
> +				     unsigned int nr);
> +
> +TRACE_EVENT(kwatch_hit,
> +	TP_PROTO(unsigned long ip, unsigned long sp, unsigned long addr,
> +		 u64 time_ns,
> +		 unsigned long *stack_entries, unsigned int stack_nr),
> +	TP_ARGS(ip, sp, addr, time_ns, stack_entries, stack_nr),
> +
> +	TP_STRUCT__entry(
> +		__field(unsigned long, ip)
> +		__field(unsigned long, sp)
> +		__field(unsigned long, addr)
> +		__field(u64, time_ns)

Move the time_ns to the first field, as unsigned long on 32 bit
architectures is 4 bytes, and this will make 4 byte "hole" in the event.


> +		__field(unsigned int, stack_nr)

Make stack_nr the last element for the same reason.

> +		__array(unsigned long, stack, KWATCH_STACK_DEPTH)

Make the above a dynamic array based on stack entries.

		__dynamic_array(unsigned long, stack, min_t(unsigned int, stack_nr,
			  KWATCH_STACK_DEPTH);


> +	),
> +
> +	TP_fast_assign(
> +		unsigned int i;
		unsigned long *stack = __get_dynamic_array(stack);
> +
> +		__entry->ip = ip;
> +		__entry->sp = sp;
> +		__entry->addr = addr;
> +		__entry->time_ns = time_ns;
> +		__entry->stack_nr = min_t(unsigned int, stack_nr,
> +					  KWATCH_STACK_DEPTH);
> +		for (i = 0; i < __entry->stack_nr; i++)
> +			__entry->stack[i] = stack_entries[i];

			stack[i] = stack_entries[i];

> +	),
> +
> +	TP_printk("KWatch HIT: time=%llu.%06lu ip=%pS addr=0x%lx%s",
> +		  __entry->time_ns / 1000000000ULL,
> +		  (unsigned long)((__entry->time_ns / 1000ULL) % 1000000ULL),
> +		  (void *)__entry->ip, __entry->addr,
> +		  kwatch_trace_print_stack(p, __entry->stack,

		  kwatch_trace_print_stack(p, __get_dynamic_array(stack),

> +					   __entry->stack_nr))
> +);
> +

-- Steve

^ permalink raw reply

* Re: [RFC PATCH v4 1/3] trace: add lock-free stackmap for stack trace deduplication
From: Steven Rostedt @ 2026-07-14 21:11 UTC (permalink / raw)
  To: Li Pengfei
  Cc: Masami Hiramatsu, Mathieu Desnoyers, Mark Rutland,
	Jonathan Corbet, Shuah Khan, linux-kernel, linux-trace-kernel,
	linux-doc, linux-kselftest, lipengfei28, zhangbo56
In-Reply-To: <20260616064119.438063-2-lipengfei28@xiaomi.com>

On Tue, 16 Jun 2026 14:41:17 +0800
Li Pengfei <ljdlns1987@gmail.com> wrote:

> --- /dev/null
> +++ b/kernel/trace/trace_stackmap.c
> @@ -0,0 +1,889 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Ftrace Stack Map - Lock-free stack trace deduplication for ftrace
> + *
> + * Modeled after tracing_map.c (used by hist triggers), this provides
> + * a lock-free hash map optimized for the ftrace hot path. The design
> + * is based on Dr. Cliff Click's non-blocking hash table algorithm.
> + *
> + * Key properties:
> + * - Lock-free insert via cmpxchg, safe in NMI/IRQ/any context
> + * - Pre-allocated element pool (zero allocation on hot path)
> + * - Linear probing with 2x over-provisioned table; probe length
> + *   bounded by FTRACE_STACKMAP_MAX_PROBE to keep worst-case lookup
> + *   cost constant even when the table is heavily loaded
> + * - Single global instance (initialized for the global trace array)
> + *
> + * Reset is a control-path operation, only allowed when tracing is
> + * stopped on the owning trace_array. The protocol is:
> + *
> + *   - atomic_cmpxchg(&resetting, 0, 1) atomically claims reset rights
> + *     and blocks new get_id() callers (they observe resetting=1 and
> + *     return -EINVAL).
> + *   - trace_types_lock serializes the tracer_tracing_is_on() check and
> + *     the destructive ring-buffer reset against tracefs writes to
> + *     tracing_on.
> + *   - synchronize_rcu() drains in-flight get_id() callers from the
> + *     ftrace callback path, which runs with preemption disabled.
> + *
> + * Online reset (with tracing active) is intentionally not supported
> + * to keep the design simple and the proof obligations small.
> + *
> + * The 32-bit jhash of the stack IPs is the hash table key. On hash
> + * collision, linear probing finds the next slot and full memcmp
> + * confirms the match.
> + *
> + * Concurrent userspace readers (cat stack_map / stack_map_bin) get
> + * a best-effort snapshot. They are coherent with the hot path
> + * (smp_load_acquire on entry->val); they are also serialized
> + * against reset via smap->reader_sem (readers take it in shared
> + * mode, reset in exclusive mode), so a reset cannot tear an
> + * iteration in progress -- it waits for active readers to drop
> + * the rwsem before clearing the map. The hot path is coordinated
> + * with reset separately, via acquire/release on smap->resetting.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/jhash.h>
> +#include <linux/seq_file.h>
> +#include <linux/kallsyms.h>
> +#include <linux/vmalloc.h>
> +#include <linux/atomic.h>
> +#include <linux/local_lock.h>
> +#include <linux/percpu.h>
> +#include <linux/random.h>
> +#include <linux/rcupdate.h>
> +#include <linux/log2.h>
> +#include <asm/local.h>
> +
> +#include "trace.h"
> +#include "trace_stackmap.h"
> +
> +/*
> + * Bound the linear-probe scan length. With a 2x over-provisioned table,
> + * a well-distributed hash gives very short probe chains. Capping at 64
> + * keeps worst-case lookup O(1) even when the table is heavily loaded
> + * with claimed-but-empty slots from pool exhaustion.
> + */
> +#define FTRACE_STACKMAP_MAX_PROBE	64
> +
> +/*
> + * Memory ordering of entry->val: published with smp_store_release()
> + * by the inserter; consumed with smp_load_acquire() by every reader
> + * that dereferences the elt (get_id, seq_show, bin_open). This pairs
> + * the writes to elt->{nr,ips,ref_count} (initialized BEFORE the
> + * publish) with the reads of those fields (which happen AFTER the
> + * load). seq_start / seq_next only test val for NULL and use the
> + * acquire load purely to keep memory ordering symmetric.
> + */
> +
> +/*
> + * Each pre-allocated element holds one unique stack trace.
> + * Fixed size: MAX_DEPTH entries regardless of actual depth.
> + */
> +struct stackmap_elt {
> +	u32		nr;		/* actual number of IPs */
> +	atomic_t	ref_count;
> +	unsigned long	ips[FTRACE_STACKMAP_MAX_DEPTH];
> +};
> +
> +/*
> + * Hash table entry: a 32-bit key (jhash of stack) + pointer to elt.
> + * key == 0 means the slot is free.
> + */
> +struct stackmap_entry {
> +	u32			key;	/* 0 = free, non-zero = jhash */
> +	struct stackmap_elt	*val;	/* NULL until fully published */
> +};
> +
> +static struct stackmap_elt *stackmap_load_elt(struct stackmap_entry *entry)
> +{
> +	/*
> +	 * Pairs with the smp_store_release() that publishes entry->val
> +	 * after fully initializing the element payload.
> +	 */
> +	return smp_load_acquire(&entry->val);
> +}
> +
> +struct ftrace_stackmap {
> +	struct trace_array	*tr;		/* owning trace_array */
> +	unsigned int		map_bits;
> +	unsigned int		map_size;	/* 1 << (map_bits + 1) */
> +	unsigned int		max_elts;	/* 1 << map_bits */
> +	u32			hash_seed;	/* per-instance jhash seed */
> +	atomic_t		next_elt;	/* index into elts pool */
> +	struct stackmap_entry	*entries;	/* hash table */
> +	struct stackmap_elt	*elts;		/* flat element pool */
> +	atomic_t		resetting;
> +	/*
> +	 * Reader/reset serialization. Held in shared mode (read lock)
> +	 * across seq_file iteration and binary snapshot construction;
> +	 * held in exclusive mode (write lock) by reset's clearing
> +	 * phase. The hot path (get_id) does not take this lock — it
> +	 * uses smp_load_acquire/smp_store_release on entry->val and
> +	 * the resetting flag for the lock-free protocol.
> +	 */
> +	struct rw_semaphore	reader_sem;
> +	/*
> +	 * Per-CPU counters using local_t. local_t increments are NMI-
> +	 * safe on all architectures (single-instruction or interrupt-
> +	 * masked) and avoid the raw_spinlock_t fallback that
> +	 * atomic64_t uses on 32-bit GENERIC_ATOMIC64 — which would
> +	 * deadlock if an NMI hit while the spinlock was held.
> +	 */
> +	local_t __percpu	*successes;	/* events served (hits + new inserts) */
> +	local_t __percpu	*drops;
> +};
> +
> +/*
> + * Cap the bits parameter to keep worst-case allocations bounded:
> + *   bits=18 → 256K elts, 512K slots, ~130 MB elt pool, ~130 MB bin
> + *             export.
> + * Smaller workloads should use the default (14) which gives 16K elts
> + * (~8 MB pool); bump bits via the ftrace_stackmap.bits= kernel
> + * parameter for higher unique-stack capacity.
> + */
> +#define FTRACE_STACKMAP_BITS_MIN	10
> +#define FTRACE_STACKMAP_BITS_MAX	18
> +#define FTRACE_STACKMAP_BITS_DEFAULT	14
> +
> +static unsigned int stackmap_map_bits = FTRACE_STACKMAP_BITS_DEFAULT;
> +static int __init stackmap_bits_setup(char *str)
> +{
> +	unsigned long val;
> +
> +	if (kstrtoul(str, 0, &val))
> +		return -EINVAL;
> +	val = clamp_val(val, FTRACE_STACKMAP_BITS_MIN, FTRACE_STACKMAP_BITS_MAX);
> +	stackmap_map_bits = val;
> +	return 0;
> +}
> +early_param("ftrace_stackmap.bits", stackmap_bits_setup);
> +
> +/* --- Element pool --- */
> +
> +static struct stackmap_elt *stackmap_get_elt(struct ftrace_stackmap *smap)
> +{
> +	int idx;
> +
> +	/*
> +	 * Fast-path early-out once the pool is fully consumed. Avoids
> +	 * the contended atomic RMW on next_elt for every traced event
> +	 * after the pool is exhausted.
> +	 */
> +	if (atomic_read(&smap->next_elt) >= smap->max_elts)
> +		return NULL;
> +
> +	idx = atomic_fetch_add_unless(&smap->next_elt, 1, smap->max_elts);
> +	if (idx < smap->max_elts)
> +		return &smap->elts[idx];
> +	return NULL;
> +}
> +
> +/* --- Create / Destroy / Reset --- */
> +
> +struct ftrace_stackmap *ftrace_stackmap_create(struct trace_array *tr)
> +{
> +	struct ftrace_stackmap *smap;
> +	unsigned int bits;
> +
> +	smap = kzalloc_obj(*smap, GFP_KERNEL);
> +	if (!smap)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* Defensive clamp: reject bogus bits even if early_param is bypassed. */
> +	bits = clamp_val(stackmap_map_bits,
> +			 FTRACE_STACKMAP_BITS_MIN,
> +			 FTRACE_STACKMAP_BITS_MAX);
> +
> +	smap->tr = tr;
> +	smap->map_bits = bits;
> +	smap->max_elts = 1U << bits;
> +	smap->map_size = 1U << (bits + 1);	/* 2x over-provision */
> +
> +	smap->entries = vzalloc(sizeof(*smap->entries) * smap->map_size);

Why not:

	smap->entries = vcalloc(smap->map_size, sizeof(*smap->entries));

?

> +	if (!smap->entries) {
> +		kfree(smap);
> +		return ERR_PTR(-ENOMEM);
> +	}

Make the error paths have:

	if (!smap->entries)
		goto fail;

> +
> +	/*
> +	 * Single large vmalloc of the element pool, indexed flat.
> +	 * At bits=18 this is 256K * sizeof(struct stackmap_elt). The
> +	 * struct is ~520 B (8 + 4 + 4 + 64*8), so total ~135 MB.
> +	 */
> +	smap->elts = vzalloc(sizeof(*smap->elts) * (size_t)smap->max_elts);

vcalloc()?

> +	if (!smap->elts) {

		goto fail;

> +		vfree(smap->entries);
> +		kfree(smap);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	smap->successes = alloc_percpu(local_t);
> +	if (!smap->successes) {

		goto fail;

> +		vfree(smap->elts);
> +		vfree(smap->entries);
> +		kfree(smap);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +	smap->drops = alloc_percpu(local_t);
> +	if (!smap->drops) {

		goto fail;

> +		free_percpu(smap->successes);
> +		vfree(smap->elts);
> +		vfree(smap->entries);
> +		kfree(smap);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	smap->hash_seed = get_random_u32();
> +	atomic_set(&smap->next_elt, 0);
> +	atomic_set(&smap->resetting, 0);
> +	init_rwsem(&smap->reader_sem);
> +
> +	return smap;

fail:

	if (smap) {
		free_percpu(smap->successes);
		vfree(smap->elts);
		vfree(smap->entries);
		kfree(smap);

// As all the above handle passing in NULL just fine.

	}

	return ERR_PTR(-ENOMEM);



> +}
> +
> +void ftrace_stackmap_destroy(struct ftrace_stackmap *smap)
> +{
> +	if (!smap || IS_ERR(smap))
> +		return;
> +	free_percpu(smap->drops);
> +	free_percpu(smap->successes);
> +	vfree(smap->elts);
> +	vfree(smap->entries);
> +	kfree(smap);
> +}
> +
> +/**
> + * ftrace_stackmap_reset - clear all entries in the stackmap
> + * @smap: the stackmap to reset
> + *
> + * Returns 0 on success, -EBUSY if another reset is already in
> + * progress, or if tracing is currently active on the owning
> + * trace_array.
> + *
> + * Online reset (with tracing active) is not supported. Caller must
> + * stop tracing first (echo 0 > tracing_on).
> + *
> + * Caller is process context (typically sysfs write handler).
> + *
> + * Protocol:
> + *   1. Atomically claim reset rights via cmpxchg on @resetting.
> + *   2. Take trace_types_lock to serialize against tracefs writes to
> + *      tracing_on.
> + *   3. Verify tracing is stopped on @smap->tr; if not, release the
> + *      claim and return -EBUSY. The resetting flag itself blocks
> + *      any subsequent get_id() callers.
> + *   4. synchronize_rcu() drains in-flight get_id() callers from the
> + *      ftrace callback path (which runs preempt-disabled).
> + *   5. Reset the ring buffer(s), then memset entries, elts, and
> + *      counters.
> + *   6. Release the resetting flag with release semantics so any new
> + *      get_id() observes a fully cleared map.
> + */
> +int ftrace_stackmap_reset(struct ftrace_stackmap *smap)
> +{
> +	struct trace_array *tr;
> +	int ret = 0;
> +
> +	if (!smap)
> +		return 0;
> +
> +	if (atomic_cmpxchg(&smap->resetting, 0, 1) != 0)
> +		return -EBUSY;
> +
> +	mutex_lock(&trace_types_lock);
> +
> +	tr = smap->tr;
> +	if (tr && tracer_tracing_is_on(tr)) {
> +		ret = -EBUSY;
> +		goto out_unlock;
> +	}
> +
> +	/*
> +	 * synchronize_rcu() itself is a full barrier; no extra smp_mb()
> +	 * is needed before it. It drains in-flight ftrace callbacks that
> +	 * may have already passed the resetting check with the old value.
> +	 */
> +	synchronize_rcu();
> +
> +	/*
> +	 * Take the reader_sem in exclusive mode. This serializes the
> +	 * memset against any tracefs reader (seq_file iteration or
> +	 * stack_map_bin snapshot) that may currently hold the rwsem
> +	 * for read. synchronize_rcu() already drained the hot path;
> +	 * this rwsem covers process-context readers that aren't
> +	 * preempt-disabled.
> +	 */
> +	down_write(&smap->reader_sem);
> +
> +	/*
> +	 * Clear the ring buffer(s) BEFORE the map, both under the write
> +	 * lock. The ring buffer may still hold TRACE_STACK_ID events
> +	 * whose stack_id points at slots we are about to free/reuse.
> +	 * Resetting the buffer first guarantees an external observer
> +	 * never sees the inconsistent "trace still has <stack_id N> but
> +	 * the map is already empty" window: it sees either (old buffer,
> +	 * old map) or (cleared buffer, old map) or (cleared buffer,
> +	 * cleared map) -- never (old buffer, cleared map).
> +	 *
> +	 * Use tracing_reset_all_cpus() (not _online_cpus) so per-CPU
> +	 * buffers belonging to currently offline CPUs are also cleared.
> +	 * The ring buffer is allocated per-possible-CPU; an offline CPU's
> +	 * buffer can still hold a TRACE_STACK_ID event written before
> +	 * the CPU went offline. tracing_reset_online_cpus() iterates
> +	 * for_each_online_buffer_cpu() and would leave that data behind
> +	 * to be observed once the CPU comes back online (or by the
> +	 * trace reader, which iterates all allocated CPU buffers),
> +	 * recreating the stale-stack_id window we are trying to close.
> +	 *
> +	 * Since reset requires tracing to be stopped, this makes "reset"
> +	 * an explicitly destructive operation on the owning trace_array,
> +	 * keeping ring-buffer stack_ids and the map coherent.
> +	 */
> +	if (tr) {
> +		tracing_reset_all_cpus(&tr->array_buffer);
> +#ifdef CONFIG_TRACER_SNAPSHOT
> +		if (tr->allocated_snapshot)
> +			tracing_reset_all_cpus(&tr->snapshot_buffer);
> +#endif
> +	}
> +
> +	memset(smap->entries, 0, sizeof(*smap->entries) * smap->map_size);
> +	memset(smap->elts, 0, sizeof(*smap->elts) * (size_t)smap->max_elts);
> +
> +	atomic_set(&smap->next_elt, 0);
> +	{

Do not add anonymous blocks in functions.

> +		int cpu;

Just declare cpu at the beginning of the function.

> +
> +		for_each_possible_cpu(cpu) {
> +			local_set(per_cpu_ptr(smap->successes, cpu), 0);
> +			local_set(per_cpu_ptr(smap->drops, cpu), 0);
> +		}
> +	}
> +
> +	up_write(&smap->reader_sem);
> +
> +out_unlock:
> +	mutex_unlock(&trace_types_lock);
> +
> +	/* Release resetting=0 so new get_id() observes a cleared map. */
> +	atomic_set_release(&smap->resetting, 0);
> +	return ret;
> +}
> +
> +/* --- Core: get_id (lock-free, NMI-safe) --- */
> +
> +int ftrace_stackmap_get_id(struct ftrace_stackmap *smap,
> +			   unsigned long *ips, unsigned int nr_entries)
> +{
> +	u32 key_hash, idx, test_key, trace_len;
> +	struct stackmap_entry *entry;
> +	struct stackmap_elt *val;
> +	int probes = 0;
> +
> +	/*
> +	 * atomic_read_acquire() pairs with atomic_set_release() in the
> +	 * reset path. This ensures that subsequent reads of entry->key
> +	 * and entry->val are ordered after this check; without acquire,
> +	 * the CPU would only have a control dependency, which orders
> +	 * subsequent stores but not loads (per LKMM).
> +	 */
> +	if (!smap || !nr_entries || atomic_read_acquire(&smap->resetting))
> +		return -EINVAL;
> +	/*
> +	 * Never truncate: a stack deeper than the map can hold must not be
> +	 * silently shortened, or two distinct traces sharing their first
> +	 * FTRACE_STACKMAP_MAX_DEPTH frames would be merged into one
> +	 * stack_id. The caller is expected to fall back to a full stack
> +	 * trace for such events. Reject defensively in case of a future
> +	 * caller that forgets this contract.
> +	 */
> +	if (nr_entries > FTRACE_STACKMAP_MAX_DEPTH)
> +		return -E2BIG;
> +
> +	trace_len = nr_entries * sizeof(unsigned long);
> +	/*
> +	 * jhash2() requires the length in u32 units and the data to be
> +	 * u32-aligned. On 64-bit kernels sizeof(unsigned long)==8, so
> +	 * trace_len is always a multiple of 8 (hence of 4). Use jhash2
> +	 * directly; the cast to u32* is safe because ips[] is naturally
> +	 * aligned to sizeof(unsigned long) >= 4.
> +	 */
> +	key_hash = jhash2((const u32 *)ips, trace_len / sizeof(u32),
> +			  smap->hash_seed);
> +	if (key_hash == 0)
> +		key_hash = 1;	/* 0 means free slot */
> +
> +	idx = key_hash >> (32 - (smap->map_bits + 1));
> +
> +	while (probes < FTRACE_STACKMAP_MAX_PROBE) {
> +		idx &= (smap->map_size - 1);
> +		entry = &smap->entries[idx];
> +		/*
> +		 * READ_ONCE() to avoid LKMM data race with concurrent
> +		 * cmpxchg(&entry->key, 0, key_hash) on this slot.
> +		 */
> +		test_key = READ_ONCE(entry->key);
> +
> +		if (test_key == key_hash) {
> +			val = stackmap_load_elt(entry);
> +			/*
> +			 * READ_ONCE(val->nr) keeps style consistent with
> +			 * the seq_show / bin_open readers. nr is write-once
> +			 * (set before publish, never modified afterwards),
> +			 * so the load is data-race-free, but READ_ONCE
> +			 * silences any analysis tool that flags a plain
> +			 * read of a field that is also read under acquire
> +			 * elsewhere.
> +			 */
> +			if (val && READ_ONCE(val->nr) == nr_entries &&
> +			    memcmp(val->ips, ips, trace_len) == 0) {
> +				/*
> +				 * ref_count is a best-effort popularity
> +				 * counter. On a long (from-boot, multi-hour)
> +				 * trace a hot stack can be hit billions of
> +				 * times. atomic_add_unless() gives true
> +				 * saturation at INT_MAX even under concurrent
> +				 * hits on multiple CPUs (a plain
> +				 * check-then-inc could let several CPUs past
> +				 * the check near the cap and still wrap).
> +				 */
> +				atomic_add_unless(&val->ref_count, 1, INT_MAX);
> +				/*
> +				 * successes/drops are best-effort throughput
> +				 * counters. Saturate at LONG_MAX so they do
> +				 * not wrap on long runs (notably where local_t
> +				 * is 32-bit), matching ref_count's behaviour.
> +				 */
> +				local_add_unless(this_cpu_ptr(smap->successes),
> +						 1, LONG_MAX);
> +				return (int)idx;
> +			}
> +			/*
> +			 * val == NULL: another CPU is mid-insert, or this
> +			 * slot is "claimed but empty" (pool exhausted).
> +			 * val != NULL but mismatch: 32-bit hash collision
> +			 * with a different stack. In both cases, advance.
> +			 */
> +		} else if (!test_key) {
> +			/*
> +			 * Free slot: try to claim it.
> +			 *
> +			 * If two CPUs race here with the same key_hash
> +			 * (same stack), one loses the cmpxchg, advances,
> +			 * and may insert the same stack at a later slot.
> +			 * This can produce a small number of duplicate
> +			 * entries under heavy contention. The trade-off
> +			 * is accepted to keep the hot path lock-free;
> +			 * ref_count is split across the duplicates and
> +			 * total memory cost is bounded by the element
> +			 * pool size.
> +			 */
> +			if (cmpxchg(&entry->key, 0, key_hash) == 0) {
> +				struct stackmap_elt *elt;
> +
> +				elt = stackmap_get_elt(smap);
> +				if (!elt) {
> +					/*
> +					 * Pool exhausted. We claimed this
> +					 * slot with cmpxchg but cannot fill
> +					 * it. Leave key set so the slot
> +					 * stays "claimed but empty" — future
> +					 * lookups treat val==NULL as a miss
> +					 * and probe past it. Cannot revert
> +					 * key=0 without racing other CPUs.
> +					 */
> +					local_add_unless(this_cpu_ptr(smap->drops),
> +							 1, LONG_MAX);
> +					return -ENOSPC;
> +				}
> +
> +				elt->nr = nr_entries;
> +				atomic_set(&elt->ref_count, 1);
> +				memcpy(elt->ips, ips, trace_len);
> +
> +				/*
> +				 * Publish elt with release semantics so the
> +				 * reader's smp_load_acquire can safely
> +				 * dereference val->nr / val->ips.
> +				 */
> +				smp_store_release(&entry->val, elt);
> +				local_add_unless(this_cpu_ptr(smap->successes),
> +						 1, LONG_MAX);
> +				return (int)idx;
> +			}
> +			/* cmpxchg failed; another CPU claimed this slot. */
> +		}
> +
> +		idx++;
> +		probes++;
> +	}
> +
> +	local_add_unless(this_cpu_ptr(smap->drops), 1, LONG_MAX);
> +	return -ENOSPC;
> +}
> +
> +/* --- Text export: /sys/kernel/debug/tracing/stack_map --- */
> +
> +struct stackmap_seq_private {
> +	struct ftrace_stackmap	*smap;
> +};
> +
> +static void *stackmap_seq_start(struct seq_file *m, loff_t *pos)
> +{
> +	struct stackmap_seq_private *priv = m->private;
> +	struct ftrace_stackmap *smap = priv->smap;
> +	u32 i;
> +
> +	if (!smap)
> +		return NULL;
> +	/*
> +	 * Take the reader_sem to serialize against ftrace_stackmap_reset(),
> +	 * which holds it for write while clearing the table. Released in
> +	 * stackmap_seq_stop(), which seq_file calls regardless of whether
> +	 * start() returned an element or NULL (per Documentation/filesystems
> +	 * /seq_file.rst: "the iterator value returned by start() or next()
> +	 * is guaranteed to be passed to a subsequent next() or stop()").
> +	 */
> +	down_read(&smap->reader_sem);
> +	for (i = *pos; i < smap->map_size; i++) {
> +		if (READ_ONCE(smap->entries[i].key) &&
> +		    stackmap_load_elt(&smap->entries[i])) {
> +			*pos = i;
> +			return &smap->entries[i];
> +		}
> +	}
> +	return NULL;
> +}
> +
> +static void *stackmap_seq_next(struct seq_file *m, void *v, loff_t *pos)
> +{
> +	struct stackmap_seq_private *priv = m->private;
> +	struct ftrace_stackmap *smap = priv->smap;
> +	u32 i;
> +
> +	if (!smap)
> +		return NULL;
> +	for (i = *pos + 1; i < smap->map_size; i++) {
> +		if (READ_ONCE(smap->entries[i].key) &&
> +		    stackmap_load_elt(&smap->entries[i])) {
> +			*pos = i;
> +			return &smap->entries[i];
> +		}
> +	}
> +	/*
> +	 * Advance *pos past the end so that on the next read() the
> +	 * subsequent stackmap_seq_start() call returns NULL and the
> +	 * iteration terminates. Without this, seq_read() would loop
> +	 * on the last element.
> +	 */
> +	*pos = smap->map_size;
> +	return NULL;
> +}
> +
> +static void stackmap_seq_stop(struct seq_file *m, void *v)
> +{
> +	struct stackmap_seq_private *priv = m->private;
> +	struct ftrace_stackmap *smap = priv->smap;
> +
> +	/*
> +	 * seq_file invokes stop() unconditionally after each iteration
> +	 * pass (see seq_read_iter / traverse), even when start() returned
> +	 * NULL. Always release here, balanced against the down_read in
> +	 * stackmap_seq_start().
> +	 */
> +	if (smap)
> +		up_read(&smap->reader_sem);
> +}
> +
> +static int stackmap_seq_show(struct seq_file *m, void *v)
> +{
> +	struct stackmap_entry *entry = v;
> +	struct stackmap_seq_private *priv = m->private;
> +	struct stackmap_elt *elt;
> +	u32 idx = entry - priv->smap->entries;
> +	u32 i, nr;
> +
> +	elt = stackmap_load_elt(entry);
> +	if (!elt)
> +		return 0;
> +
> +	nr = READ_ONCE(elt->nr);
> +	if (nr > FTRACE_STACKMAP_MAX_DEPTH)
> +		nr = FTRACE_STACKMAP_MAX_DEPTH;
> +
> +	seq_printf(m, "stack_id %u [ref %u, depth %u]\n",
> +		   idx, atomic_read(&elt->ref_count), nr);
> +	for (i = 0; i < nr; i++) {
> +		unsigned long ip = elt->ips[i];
> +
> +		/*
> +		 * Mirror trace_stack_print(): __ftrace_trace_stack()
> +		 * may replace trampoline addresses with
> +		 * FTRACE_TRAMPOLINE_MARKER before the stack reaches the
> +		 * map, and normal addresses must go through
> +		 * trace_adjust_address() (KASLR / module text delta)
> +		 * before symbolization. Without this the export would
> +		 * print a bogus symbol for the marker and unadjusted
> +		 * addresses for everything else.
> +		 */
> +		if (ip == FTRACE_TRAMPOLINE_MARKER) {
> +			seq_printf(m, "  [%u] [FTRACE TRAMPOLINE]\n", i);
> +			continue;
> +		}
> +		seq_printf(m, "  [%u] %pS\n", i,
> +			   (void *)trace_adjust_address(priv->smap->tr, ip));
> +	}
> +	seq_putc(m, '\n');
> +	return 0;
> +}
> +
> +static const struct seq_operations stackmap_seq_ops = {
> +	.start	= stackmap_seq_start,
> +	.next	= stackmap_seq_next,
> +	.stop	= stackmap_seq_stop,
> +	.show	= stackmap_seq_show,
> +};
> +
> +static int stackmap_open(struct inode *inode, struct file *file)
> +{
> +	struct stackmap_seq_private *priv;
> +	struct seq_file *m;
> +	int ret;
> +
> +	ret = seq_open_private(file, &stackmap_seq_ops,
> +			       sizeof(struct stackmap_seq_private));
> +	if (ret)
> +		return ret;
> +	m = file->private_data;
> +	priv = m->private;
> +	priv->smap = inode->i_private;
> +	return 0;
> +}
> +
> +/*
> + * Accept exactly "0" or "reset" (optionally followed by a single newline).
> + */
> +static bool stackmap_write_is_reset(const char *buf, size_t n)
> +{
> +	if (n > 0 && buf[n - 1] == '\n')
> +		n--;
> +	return (n == 1 && buf[0] == '0') ||
> +	       (n == 5 && memcmp(buf, "reset", 5) == 0);
> +}
> +
> +static ssize_t stackmap_write(struct file *file, const char __user *ubuf,
> +			      size_t count, loff_t *ppos)
> +{
> +	struct seq_file *m = file->private_data;
> +	struct stackmap_seq_private *priv = m->private;
> +	char buf[8];
> +	size_t n = min(count, sizeof(buf) - 1);
> +	int ret;
> +
> +	if (n == 0)
> +		return -EINVAL;
> +	if (copy_from_user(buf, ubuf, n))
> +		return -EFAULT;
> +	buf[n] = '\0';
> +
> +	if (!stackmap_write_is_reset(buf, n))
> +		return -EINVAL;
> +
> +	/*
> +	 * ftrace_stackmap_reset() atomically claims reset rights via
> +	 * cmpxchg and returns -EBUSY if another reset is in progress
> +	 * or if tracing is active.
> +	 */
> +	ret = ftrace_stackmap_reset(priv->smap);
> +	if (ret)
> +		return ret;
> +	return count;
> +}
> +
> +const struct file_operations ftrace_stackmap_fops = {
> +	.open		= stackmap_open,
> +	.read		= seq_read,
> +	.write		= stackmap_write,
> +	.llseek		= seq_lseek,
> +	.release	= seq_release_private,
> +};
> +
> +/* --- Stats --- */
> +
> +static int stackmap_stat_show(struct seq_file *m, void *v)
> +{
> +	struct ftrace_stackmap *smap = m->private;
> +	u64 successes = 0, drops = 0;
> +	u32 entries;
> +	int cpu;
> +
> +	if (!smap) {
> +		seq_puts(m, "stackmap not initialized\n");
> +		return 0;
> +	}
> +
> +	entries = atomic_read(&smap->next_elt);
> +	for_each_possible_cpu(cpu) {
> +		successes += local_read(per_cpu_ptr(smap->successes, cpu));
> +		drops += local_read(per_cpu_ptr(smap->drops, cpu));
> +	}
> +
> +	seq_printf(m, "entries:      %u / %u\n", entries, smap->max_elts);
> +	seq_printf(m, "table_size:   %u\n", smap->map_size);
> +	seq_printf(m, "successes:    %llu\n", successes);
> +	seq_printf(m, "drops:        %llu\n", drops);
> +	if (successes + drops > 0)
> +		seq_printf(m, "success_rate: %llu%%\n",
> +			   successes * 100 / (successes + drops));
> +	return 0;
> +}
> +
> +static int stackmap_stat_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, stackmap_stat_show, inode->i_private);
> +}
> +
> +const struct file_operations ftrace_stackmap_stat_fops = {
> +	.open		= stackmap_stat_open,
> +	.read		= seq_read,
> +	.llseek		= seq_lseek,
> +	.release	= single_release,
> +};
> +
> +/* --- Binary export --- */
> +
> +struct stackmap_bin_snapshot {
> +	/*
> +	 * Use u64 (not size_t) so data[] is 8-byte aligned on both
> +	 * 32-bit and 64-bit architectures. The IP array within data[]
> +	 * is accessed as u64*, which would alignment-fault on strict
> +	 * architectures (e.g. older ARM, SPARC) if data[] started at
> +	 * a 4-byte boundary.
> +	 */
> +	u64	size;
> +	char	data[];
> +};
> +
> +static int stackmap_bin_open(struct inode *inode, struct file *file)
> +{
> +	struct ftrace_stackmap *smap = inode->i_private;
> +	struct stackmap_bin_snapshot *snap;
> +	struct ftrace_stackmap_bin_header *hdr;
> +	size_t alloc_size, off;
> +	u32 nr_entries, i, nr_stacks;
> +
> +	if (!smap)
> +		return -ENODEV;
> +
> +	/*
> +	 * Worst-case allocation size: every populated entry uses a
> +	 * full-depth stack. The (+1) gives one slack slot in case a
> +	 * concurrent insert lands between this snapshot and iteration.
> +	 * The loop below performs an explicit bounds check anyway.
> +	 *
> +	 * At bits=18 this caps at ~135 MB. The file is mode 0440
> +	 * (TRACE_MODE_READ), so only privileged users can open it.
> +	 */
> +	nr_entries = atomic_read(&smap->next_elt);
> +	alloc_size = sizeof(*hdr) + (nr_entries + 1) *
> +		     (sizeof(struct ftrace_stackmap_bin_entry) +
> +		      FTRACE_STACKMAP_MAX_DEPTH * sizeof(u64));

Really should have ftrace_stackmap_bin_entry have a flexible array:

(move struct ftrace_stackmap_bin_entry *e to top)

	alloc_size = sizeof(*hdr) + (nr_entries + 1) *
		struct_size(e, ips, FTRACE_STACKMAP_MAX_DEPTH);

> +
> +	snap = vmalloc(sizeof(*snap) + alloc_size);
> +	if (!snap)
> +		return -ENOMEM;
> +
> +	hdr = (struct ftrace_stackmap_bin_header *)snap->data;
> +	hdr->magic = FTRACE_STACKMAP_BIN_MAGIC;
> +	hdr->version = FTRACE_STACKMAP_BIN_VERSION;
> +	hdr->reserved = 0;
> +	off = sizeof(*hdr);
> +	nr_stacks = 0;
> +
> +	/*
> +	 * Take reader_sem to serialize against ftrace_stackmap_reset(),
> +	 * which clears the table and elt pool under the write lock.
> +	 */
> +	down_read(&smap->reader_sem);
> +
> +	for (i = 0; i < smap->map_size; i++) {
> +		struct stackmap_entry *entry = &smap->entries[i];
> +		struct stackmap_elt *elt;

> +		struct ftrace_stackmap_bin_entry *e;

move to top of function.

> +		u64 *ips_out;
> +		u32 k, nr;
> +
> +		if (!READ_ONCE(entry->key))
> +			continue;
> +		elt = stackmap_load_elt(entry);
> +		if (!elt)
> +			continue;
> +
> +		nr = READ_ONCE(elt->nr);
> +		if (nr > FTRACE_STACKMAP_MAX_DEPTH)
> +			nr = FTRACE_STACKMAP_MAX_DEPTH;
> +
> +		/* Bounds check: stop if we would overflow the allocation. */
> +		if (off + sizeof(*e) + nr * sizeof(u64) > alloc_size)

		if (off + struct_size(e, ips, nr) > alloc_size)

> +			break;
> +
> +		e = (struct ftrace_stackmap_bin_entry *)(snap->data + off);
> +		e->stack_id = i;
> +		e->nr = nr;
> +		e->ref_count = atomic_read(&elt->ref_count);
> +		e->reserved = 0;

> +		off += sizeof(*e);

delete the above.

> +
> +		ips_out = (u64 *)(snap->data + off);

		ips_out = e->ips;

> +		for (k = 0; k < nr; k++) {
> +			unsigned long ip = elt->ips[k];
> +
> +			/*
> +			 * Emit the trampoline marker verbatim so userspace
> +			 * can render it as [FTRACE TRAMPOLINE]; pass every
> +			 * other address through trace_adjust_address() so the
> +			 * binary export follows the same address-adjustment
> +			 * rules as the text export.
> +			 */
> +			if (ip == FTRACE_TRAMPOLINE_MARKER)
> +				ips_out[k] = (u64)FTRACE_TRAMPOLINE_MARKER;
> +			else
> +				ips_out[k] = (u64)trace_adjust_address(smap->tr, ip);
> +		}
> +		off += nr * sizeof(u64);

		off += struct_size(e, ips, nr);

> +		nr_stacks++;
> +	}
> +
> +	up_read(&smap->reader_sem);
> +
> +	hdr->nr_stacks = nr_stacks;
> +	snap->size = off;
> +	file->private_data = snap;
> +	return 0;
> +}
> +
> +static ssize_t stackmap_bin_read(struct file *file, char __user *ubuf,
> +				 size_t count, loff_t *ppos)
> +{
> +	struct stackmap_bin_snapshot *snap = file->private_data;
> +
> +	if (!snap)
> +		return -EINVAL;
> +	return simple_read_from_buffer(ubuf, count, ppos, snap->data, snap->size);
> +}
> +
> +static int stackmap_bin_release(struct inode *inode, struct file *file)
> +{
> +	vfree(file->private_data);
> +	return 0;
> +}
> +
> +const struct file_operations ftrace_stackmap_bin_fops = {
> +	.open		= stackmap_bin_open,
> +	.read		= stackmap_bin_read,
> +	.llseek		= default_llseek,
> +	.release	= stackmap_bin_release,
> +};
> diff --git a/kernel/trace/trace_stackmap.h b/kernel/trace/trace_stackmap.h
> new file mode 100644
> index 000000000000..7c2e5ab9d36d
> --- /dev/null
> +++ b/kernel/trace/trace_stackmap.h
> @@ -0,0 +1,57 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef _TRACE_STACKMAP_H
> +#define _TRACE_STACKMAP_H
> +
> +#include <linux/types.h>
> +#include <linux/atomic.h>
> +
> +#define FTRACE_STACKMAP_MAX_DEPTH	64
> +
> +/* Binary export format */
> +#define FTRACE_STACKMAP_BIN_MAGIC	0x46534D42	/* 'FSMB' */
> +#define FTRACE_STACKMAP_BIN_VERSION	1
> +
> +struct ftrace_stackmap_bin_header {
> +	u32 magic;
> +	u32 version;
> +	u32 nr_stacks;
> +	u32 reserved;
> +};
> +
> +struct ftrace_stackmap_bin_entry {
> +	u32 stack_id;
> +	u32 nr;
> +	u32 ref_count;
> +	u32 reserved;
> +	/* followed by u64 ips[nr] */

Why not make this a flexible array?

	u64 ips[];

Then the code can be simpler as described above.

-- Steve


> +};
> +
> +struct trace_array;
> +
> +#ifdef CONFIG_FTRACE_STACKMAP
> +
> +struct ftrace_stackmap;
> +
> +struct ftrace_stackmap *ftrace_stackmap_create(struct trace_array *tr);
> +void ftrace_stackmap_destroy(struct ftrace_stackmap *smap);
> +int ftrace_stackmap_get_id(struct ftrace_stackmap *smap,
> +			   unsigned long *ips, unsigned int nr_entries);
> +int ftrace_stackmap_reset(struct ftrace_stackmap *smap);
> +
> +extern const struct file_operations ftrace_stackmap_fops;
> +extern const struct file_operations ftrace_stackmap_stat_fops;
> +extern const struct file_operations ftrace_stackmap_bin_fops;
> +
> +#else
> +
> +struct ftrace_stackmap;
> +static inline struct ftrace_stackmap *
> +ftrace_stackmap_create(struct trace_array *tr) { return NULL; }
> +static inline void ftrace_stackmap_destroy(struct ftrace_stackmap *s) { }
> +static inline int ftrace_stackmap_get_id(struct ftrace_stackmap *s,
> +					 unsigned long *ips, unsigned int n)
> +{ return -EOPNOTSUPP; }
> +static inline int ftrace_stackmap_reset(struct ftrace_stackmap *s) { return 0; }
> +
> +#endif
> +#endif /* _TRACE_STACKMAP_H */


^ permalink raw reply

* Re: [PATCH v2] PCI: rcar-gen4: Isolate driver to ARM64
From: Bjorn Helgaas @ 2026-07-14 21:10 UTC (permalink / raw)
  To: Marek Vasut, Manivannan Sadhasivam
  Cc: linux-pci, kernel test robot, Krzysztof Wilczyński,
	Bjorn Helgaas, Catalin Marinas, Conor Dooley, Geert Uytterhoeven,
	Krzysztof Kozlowski, Lorenzo Pieralisi, Manivannan Sadhasivam,
	Marc Zyngier, Rob Herring, Yoshihiro Shimoda, devicetree,
	linux-arm-kernel, linux-doc, linux-kernel, linux-renesas-soc
In-Reply-To: <20260714131957.38067-1-marek.vasut+renesas@mailbox.org>

On Tue, Jul 14, 2026 at 03:19:27PM +0200, Marek Vasut wrote:
> The driver includes linux/irqchip/arm-gic-v3.h which pulls in headers
> which are available only on ARM and ARM64, on other architectures the
> headers are not present and the driver fails to build. This driver is
> used only on ARM64 hardware, isolate its build only to ARM64 to avoid
> build failures on other architectures.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202607100310.iQw5m9Uo-lkp@intel.com/
> Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>

Mani, I assume you'll squash this into 89bded511a66 ("PCI: rcar-gen4:
Configure AXIINTC if iMSI-RX is not used") so it's connected to the
addition of the linux/irqchip/arm-gic-v3.h include and there's no
bisection hole?

> ---
> Cc: "Krzysztof Wilczyński" <kwilczynski@kernel.org>
> Cc: Bjorn Helgaas <bhelgaas@google.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: Geert Uytterhoeven <geert+renesas@glider.be>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Manivannan Sadhasivam <mani@kernel.org>
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: Rob Herring <robh@kernel.org>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: devicetree@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-pci@vger.kernel.org
> Cc: linux-renesas-soc@vger.kernel.org
> ---
> V2: This is a rework of PCI: rcar-gen4: Inline GIC_TRANSLATER offset macro
>     which isolates the driver build to ARM64 via Kconfig instead:
>     https://lore.kernel.org/linux-pci/CAMuHMdVvWE7YZgKvreSn_vJLOVD4eMmn3TCGOyqSXksqjBCwvg@mail.gmail.com/
>     https://lore.kernel.org/linux-pci/20260714110041.GA1349622@bhelgaas/
> ---
>  drivers/pci/controller/dwc/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
> index 49a7a2c50ca15..3260d916110b2 100644
> --- a/drivers/pci/controller/dwc/Kconfig
> +++ b/drivers/pci/controller/dwc/Kconfig
> @@ -346,7 +346,7 @@ config PCIE_RCAR_GEN4
>  
>  config PCIE_RCAR_GEN4_HOST
>  	tristate "Renesas R-Car Gen4 PCIe controller (host mode)"
> -	depends on ARCH_RENESAS || COMPILE_TEST
> +	depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST)
>  	depends on PCI_MSI
>  	select PCIE_DW_HOST
>  	select PCIE_RCAR_GEN4
> @@ -357,7 +357,7 @@ config PCIE_RCAR_GEN4_HOST
>  
>  config PCIE_RCAR_GEN4_EP
>  	tristate "Renesas R-Car Gen4 PCIe controller (endpoint mode)"
> -	depends on ARCH_RENESAS || COMPILE_TEST
> +	depends on ARM64 && (ARCH_RENESAS || COMPILE_TEST)
>  	depends on PCI_ENDPOINT
>  	select PCIE_DW_EP
>  	select PCIE_RCAR_GEN4
> -- 
> 2.53.0
> 

^ permalink raw reply

* RE: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
From: Shenwei Wang (OSS) @ 2026-07-14 21:10 UTC (permalink / raw)
  To: Andrew Lunn, Shenwei Wang (OSS)
  Cc: Mathieu Poirier, Linus Walleij, Bartosz Golaszewski,
	Jonathan Corbet, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Frank Li, Sascha Hauer, Shuah Khan,
	linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
	Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
	linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, dl-linux-imx,
	Arnaud POULIQUEN, b-padhi@ti.com
In-Reply-To: <68a9dd77-a07b-4ea5-ad66-9e2bda490d20@lunn.ch>



> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Tuesday, July 14, 2026 3:23 PM
> To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>; Linus Walleij
> <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski
> <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn Andersson
> <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com
> Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> bus
> 
> > The two fields above are required for rpmsg-gpio, but not for virtio-gpio.
> >
> > In the rpmsg-gpio case, interrupt detection and handling occur on the
> > remote processor. The interrupt information (such as the GPIO line and
> > trigger type) must therefore be sent to Linux through this notification message.
> >
> > In contrast, for virtio-gpio, interrupt handling is performed on the
> > local processor. Since Linux already has all the necessary interrupt context, the
> information is not needed.
> 
> Are you sure about that?
> 
> virtio_gpio_irq_set_type() sets:
> 

Why are you bringing up virtio_gpio_irq_set_type() here? The command path is already 
fully aligned with the existing virtio-gpio implementation.

The gap we are discussing is the interrupt notification message coming from the remote side. 
That is the topic under discussion.

Shenwei

>         irq_line->type = type;
>         irq_line->update_pending = true;
> 
> virtio_gpio_irq_bus_sync_unlock() looks at update_pending and does
> virtio_gpio_req(), passing irq_line->type as type.
> 
> This then gets filled into:
> 
> /* Virtio GPIO Request / Response */
> struct virtio_gpio_request {
> 	__le16 type;
> 	__le16 gpio;
> 	__le32 value;
> };
> 
> which gets scatter/gathered over the virtqueue to the peer.
> 
>       Andrew

^ permalink raw reply

* [PATCH v2] docs: translations: pt_BR: process: email-clients: traduz para pt_BR
From: Ygor Otavio @ 2026-07-14 21:01 UTC (permalink / raw)
  To: danielmaraboo; +Cc: linux-doc, corbet, Ygor Otavio

Translates the documentation regarding email clients info for Linux
into Brazilian Portuguese, maintaining consistency with original
formatting rules.
For V2, the errors "bullet list ends without a blank line" and
"inline interpreted text start-string without end-string" were fixed.
The others errors that appeared after the submission of v2 were also
fixed.

Signed-off-by: Ygor Otavio <ygorotavio.sjc@gmail.com>
---
 .../pt_BR/process/email-clients.rst           | 368 ++++++++++++++++++
 1 file changed, 368 insertions(+)
 create mode 100644 Documentation/translations/pt_BR/process/email-clients.rst

diff --git a/Documentation/translations/pt_BR/process/email-clients.rst b/Documentation/translations/pt_BR/process/email-clients.rst
new file mode 100644
index 000000000..407934c7c
--- /dev/null
+++ b/Documentation/translations/pt_BR/process/email-clients.rst
@@ -0,0 +1,368 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+Informações sobre clientes de email para Linux
+==============================================
+
+Git
+---
+
+Hoje em dia a maioria dos desenvolvedores usa ``git send-email`` em vez de
+clientes de email comuns. A página de manual desse comando é bem útil. No lado
+de quem recebe, os mantenedores usam ``git am`` para aplicar os patches.
+
+Se você é novo no ``git``, envie seu primeiro patch para si mesmo. Salve-o
+como texto bruto, incluindo todos os cabeçalhos. Execute ``git am raw_email.txt``
+e então revise o changelog com ``git log``. Quando isso funcionar, envie o
+patch para a(s) lista(s) de discussão apropriada(s).
+
+Preferências Gerais
+-------------------
+
+Os patches para o kernel Linux são enviados por email, preferencialmente como
+texto inline no corpo da mensagem. Alguns mantenedores aceitam anexos, mas,
+nesse caso, os anexos devem ter o content-type ``text/plain``. Contudo, anexos
+são, em geral, desaconselhados porque dificultam citar trechos do patch durante
+o processo de revisão.
+
+Também é altamente recomendável que você use plain text no corpo do email, tanto
+para patches quanto para outras mensagens. https://useplaintext.email pode ser
+útil para obter informações sobre como configurar seu cliente de email preferido,
+além de listar clientes de email recomendados caso você ainda não tenha preferência.
+
+Clientes de email usados para patches do kernel Linux devem enviar o texto do
+patch sem alterações. Por exemplo, eles não devem modificar ou apagar tabs ou
+espaços, mesmo no início ou no fim das linhas.
+
+Não envie patches com ``format=flowed``. Isso pode causar quebras de linha
+inesperadas e indesejadas.
+
+Não deixe seu cliente de email fazer quebra automática de linha para você.
+Isso também pode corromper seu patch.
+
+Clientes de email não devem modificar a codificação do conjunto de caracteres do
+texto. Patches enviados por email devem usar apenas codificação ASCII ou UTF-8.
+Se você configurar seu cliente de email para enviar mensagens com codificação
+UTF-8, você evita alguns possíveis problemas de charset.
+
+Clientes de email devem gerar e manter "References:" ou "In-Reply-To:"
+cabeçalhos para que o encadeamento de mensagens não seja quebrado.
+
+Copiar e colar (ou recortar e colar) geralmente não funciona para patches
+porque tabs são convertidos em espaços. Usar xclipboard, xclip e/ou xcutsel
+pode funcionar, mas é melhor testar isso você mesmo ou simplesmente evitar
+copiar e colar.
+
+Não use assinaturas PGP/GPG em emails que contenham patches. Isso quebra muitos
+scripts que leem e aplicam os patches.
+(Isso deve ser corrigível.)
+
+É uma boa ideia enviar um patch para si mesmo, salvar a mensagem recebida e
+aplicá-la com sucesso com o comando 'patch' antes de enviar patches para as
+listas de discussão do Linux.
+
+Algumas dicas de clientes de email (MUA)
+----------------------------------------
+
+Aqui estão algumas dicas específicas de configuração de MUA para editar e enviar
+patches para o kernel Linux. Estas dicas não pretendem ser resumos completos da
+configuração dos pacotes de software.
+
+Legenda:
+
+- TUI = Interface de Usuário Baseada em Texto
+- GUI = Interface Gráfica de Usuário
+
+Alpine (TUI)
+************
+
+Opções de configuração:
+
+Na seção :menuselection:`Preferências de Envio`:
+
+- :menuselection:`Não Envie Texto com Quebra de Linha Automática` deve estar ``habilitado``
+- :menuselection:`Remover Espaços em Branco Antes de Enviar` deve estar ``desabilitado``
+
+Ao compor a mensagem, o cursor deve ser posicionado onde o patch deverá aparecer,
+e então pressionar `CTRL-R` permite especificar o arquivo de patch a ser
+inserido na mensagem.
+
+Claws Mail (GUI)
+****************
+
+Funciona. Algumas pessoas usam isso com sucesso para patches.
+
+Para inserir um patch, use :menuselection:`Mensagem-->Inserir Arquivo`(`CTRL-I`)
+ou um editor externo.
+
+Se o patch inserido precisar ser editado na janela de composição do
+Claws, a opção "Quebra automática" em
+:menuselection:`Configuração-->Preferências-->Escrever-->Quebra de linha`
+deve estar desabilitada.
+
+Evolution (GUI)
+***************
+
+Algumas pessoas usam isso com sucesso para patches.
+
+Ao compor o e-mail, selecione: Preformatado
+  em :menuselection:`Formatar-->Estilo de Parágrafo-->Preformatado` (`CTRL-7`)
+  ou na barra de ferramentas
+
+Depois use:
+:menuselection:`Inserir-->Arquivo de Texto...` (`ALT-N x`)
+para inserir o patch.
+
+Você também pode usar ``diff -Nru old.c new.c | xclip``, selecionar
+:menuselection:`Preformatado`, depois colar com o botão do meio.
+
+Kmail (GUI)
+***********
+
+Algumas pessoas usam o KMail com sucesso para patches.
+
+A configuração padrão de não compor em HTML é apropriada; não a habilite.
+
+Ao compor um email, em opções, desmarque “quebra de linha automática”. A única
+desvantagem é que qualquer texto que você digitar no email não será quebrado
+automaticamente, então você terá que quebrar manualmente o texto antes do patch.
+A maneira mais fácil é compor o email com quebra de linha automática habilitado,
+depois salvá-lo como rascunho. Depois de abri-lonovamente dos rascunhos, ele
+estará com quebras de linha rígidas e você poderá desmarcar “quebra de linha
+automática” sem perder a quebra existente.
+
+No final do seu email, coloque o delimitador de patch comumente usado antes de
+inserir o patch: três hífens (``---``).
+
+Então, no menu :menuselection:`Mensagem`, selecione :menuselection:`inserir arquivo`
+e escolha o seu patch. Como benefício adicional, você pode personalizar a barra
+de ferramentas de criação de mensagens e colocar o ícone :menuselection:`inserir arquivo` lá.
+
+Deixe a janela do compositor larga o suficiente para que nenhuma linha seja
+quebrada. A partir do KMail 1.13.5 (KDE 4.5.4), o KMail aplica quebra de linha
+ao enviar o email se as linhas quebrarem na janela do compositor. Ter a quebrade
+linha desativada no menu Opções não é suficiente. Por isso se o seu patch tiver
+linhas muito longas, você deve deixar a janela do seu compositor bem larga antes
+de enviar o email. Veja: https://bugs.kde.org/show_bug.cgi?id=174034
+
+Você pode assinar anexos com GPG com segurança, mas texto em linha é preferido
+para patches, então não os assine com GPG. Assinar patches que foram inseridos
+como texto em linha torna mais difícil extraí-los de sua codificação 7 bits.
+
+Se você absolutamente precisar enviar patches como anexos em vez de inseri-los
+como texto, clique com o botão direito no anexo e selecione
+:menuselection:`propriedades`, e destaque :menuselection:`Sugerir exibição automática`
+para fazer o anexo ser exibido como texto inserido e ficar mais fácil de
+visualizar.
+
+Ao salvar patches enviados como texto inserido, selecione o email que contém o
+patch no painel da lista de mensagens, clique com o botão direito e selecione
+:menuselection:`salvar como`. Você pode usar o email inteiro sem alterações como
+patch se ele tiver sido composto corretamente. Emails são salvos como leitura e
+gravação apenas para o usuário, então você terá que chmodá-los para torná-los
+legíveis por grupo e por todos se copiá-los para outro lugar.
+
+Lotus Notes (GUI)
+*****************
+
+Fuja dele.
+
+IBM Verse (Web GUI)
+*******************
+
+Veja Lotus Notes.
+
+Mutt (TUI)
+**********
+
+Muitos desenvolvedores Linux usam ``mutt``, então deve funcionar muito bem.
+
+O mutt não vem com editor, então qualquer editor que você use deve ser usado de
+forma que não haja quebras de linha automáticas. A maioria dos editores tem uma
+opção :menuselection:`Inserir Arquivo` que insere o conteúdo de um arquivo sem
+alterações.
+
+Para usar ``vim`` com o mutt::
+
+  set editor="vi"
+
+Se estiver usando xclip, digite o comando::
+
+  :set paste
+
+antes do botão do meio ou shift-insert ou use::
+
+  :r filename
+
+se você quiser incluir o patch inline.
+(a)ttach funciona bem sem ``set paste``.
+
+Você também pode gerar patches com ``git format-patch`` e depois usar o Mutt
+para enviá-los::
+
+    $ mutt -H 0001-some-bug-fix.patch
+
+Opções de configuração:
+
+Deve funcionar com as configurações padrão. No entanto, é uma boa ideia definir
+o ``send_charset`` como::
+
+  set send_charset="us-ascii:utf-8"
+
+O Mutt é altamente personalizável. Aqui está uma configuração mínima para
+começar a usar o Mutt para enviar patches pelo Gmail::
+
+  # .muttrc
+  # ================  IMAP  ====================
+  set imap_user = 'seuusuario@gmail.com'
+  set imap_pass = 'suasenha'
+  set spoolfile = imaps://imap.gmail.com/INBOX
+  set folder = imaps://imap.gmail.com/
+  set record="imaps://imap.gmail.com/[Gmail]/Sent Mail"
+  set postponed="imaps://imap.gmail.com/[Gmail]/Drafts"
+  set mbox="imaps://imap.gmail.com/[Gmail]/All Mail"
+
+  # ================  SMTP  ====================
+  set smtp_url = "smtp://usuario@smtp.gmail.com:587/"
+  set smtp_pass = $imap_pass
+  set ssl_force_tls = yes # Exige conexão criptografada
+
+  # ================  Composição  ====================
+  set editor = `echo \$EDITOR`
+  set edit_headers = yes  # Exibe os cabeçalhos ao editar
+  set charset = UTF-8     # valor de $LANG; também usado como
+                          # fallback para send_charset
+  # Remetente, endereço de e-mail e linha de assinatura devem
+  # corresponder
+  unset use_domain        # porque joe@localhost é constrangedor
+  set realname = "SEU NOME"
+  set from = "usuario@gmail.com"
+  set use_from = yes
+
+A documentação do Mutt tem muito mais informações:
+
+    https://gitlab.com/muttmua/mutt/-/wikis/UseCases/Gmail
+
+    http://www.mutt.org/doc/manual/
+
+Pine (TUI)
+**********
+
+O Pine já teve alguns problemas de truncamento de espaços em branco no passado,
+mas isso deve estar todo corrigido agora.
+
+Use o alpine (sucessor do pine) se possível.
+
+Opções de configuração:
+
+- ``quell-flowed-text`` é necessário para versões recentes
+- a opção ``no-strip-whitespace-before-send`` é necessária
+
+
+Sylpheed (GUI)
+**************
+
+- Funciona bem para inserir texto inline (ou usando anexos).
+- Permite o uso de um editor externo.
+- É lento em pastas grandes.
+- Não fará autenticação TLS SMTP sobre uma conexão não-SSL.
+- Tem uma barra de régua útil na janela de composição.
+- Adicionar endereços ao catálogo de endereços não reconhece corretamente o nome
+  de exibição.
+
+Thunderbird (GUI)
+*****************
+
+O Thunderbird é um clone do Outlook que gosta de bagunçar o texto, mas há formas
+de convencê-lo a se comportar.
+
+Depois de fazer as modificações, incluindo a instalação das extensões, você
+precisa reiniciar o Thunderbird.
+
+- Permitir o uso de um editor externo:
+
+  A forma mais fácil de trabalhar com patches no Thunderbird é usar extensões
+  que abrem seu editor externo favorito.
+
+  Aqui estão alguns exemplos de extensões capazes de fazer isso.
+
+  - "Editor Externo Reativado"
+
+    https://github.com/Frederick888/external-editor-revived
+
+    https://addons.thunderbird.net/en-GB/thunderbird/addon/external-editor-revived/
+
+    É necessário instalar um "host de mensagens nativas".
+    Leia a wiki, que pode ser encontrada aqui:
+    https://github.com/Frederick888/external-editor-revived/wiki
+
+  - "Editor Externo"
+
+    https://github.com/exteditor/exteditor
+
+    Para isso, baixe e instale a extensão, depois abra a janela de
+    :menuselection:`compor`, adicione um botão para ela usando
+    :menuselection:`Visualizar-->Barras de Ferramentas-->Personalizar...`
+    e então basta clicar no novo botão quando quiser usar o editor externo.
+
+    Observe que o "Editor Externo" exige que seu editor não faça fork, ou seja,
+    o editor não deve retornar antes de fechar. Pode ser necessário passar flags
+    adicionais ou alterar as configurações do seu editor. Principalmente se você
+    estiver usando o gvim, deve passar a opção -f para o gvim colocando
+    ``/usr/bin/gvim --nofork"`` (se o binário estiver em ``/usr/bin``) no campo
+    de editor de texto nas configurações de :menuselection:`editor externo`. Se
+    estiver usando outro editor, consulte seu manual para descobrir como fazer isso.
+
+Para colocar juízo no editor interno, faça o seguinte:
+
+- Edite as configurações do Thunderbird para que ele não use ``format=flowed``!
+  Vá até a janela principal e encontre o botão do menu suspenso principal.
+  :menuselection:`Menu Principal-->Preferências-->Geral-->Editor de Configurações...`
+  para abrir o editor de registro do Thunderbird.
+
+  - Defina ``mailnews.send_plaintext_flowed`` como ``false``
+
+    - Altere ``mailnews.wraplength`` de ``72`` para ``0`` **ou** instale a
+      extensão "Toggle Line Wrap"
+
+      https://github.com/jan-kiszka/togglelinewrap
+
+      https://addons.thunderbird.net/thunderbird/addon/toggle-line-wrap
+
+      para controlar esse registro dinamicamente.
+
+- Não escreva mensagens em HTML! Vá até a janela principal
+  :menuselection:`Menu Principal-->Configurações da Conta-->suaconta@servidor.algo-->Composição e Endereçamento`!
+  Lá você pode desabilitar a opção "Compor mensagens em formato HTML".
+
+- Abra mensagens apenas como texto simples! Vá até a janela principal
+  :menuselection:`Menu Principal-->Visualizar-->Corpo da Mensagem Como-->Texto Simples`!
+
+TkRat (GUI)
+***********
+
+Funciona. Use "Inserir arquivo..." ou um editor externo.
+
+Gmail (Web GUI)
+***************
+
+Não funciona para enviar patches.
+
+O cliente web do Gmail converte tabulações em espaços automaticamente.
+
+Ao mesmo tempo, ele quebra linhas a cada 78 caracteres com quebras de linha no
+estilo CRLF, embora o problema de tab para espaço possaser resolvido com um
+editor externo.
+
+Outro problema é que o Gmail codifica em base64 qualquer mensagem que tenha um
+caractere não-ASCII. Isso inclui coisas como nomes europeus.
+
+HacKerMaiL (TUI)
+****************
+
+HacKerMaiL (hkml) é uma ferramenta simples de gerenciamento de e-mails baseada
+em public-inbox que não exige inscrição em listas de discussão. É desenvolvida
+e mantida pelo mantenedor do DAMON e visa oferecer suporte a fluxos de trabalho
+de desenvolvimento simples para o DAMON e para subsistemas gerais do kernel.
+Consulte o README (https://github.com/sjp38/hackermail/blob/master/README.md)
+para mais detalhes.
+
-- 
2.55.0


^ permalink raw reply related

* RE: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
From: Shenwei Wang (OSS) @ 2026-07-14 20:27 UTC (permalink / raw)
  To: Andrew Lunn, Shenwei Wang (OSS)
  Cc: Mathieu Poirier, Linus Walleij, Bartosz Golaszewski,
	Jonathan Corbet, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Frank Li, Sascha Hauer, Shuah Khan,
	linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
	Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
	linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, dl-linux-imx,
	Arnaud POULIQUEN, b-padhi@ti.com
In-Reply-To: <680d0633-cdec-4545-9114-79bfd6eaac41@lunn.ch>



> -----Original Message-----
> From: Andrew Lunn <andrew@lunn.ch>
> Sent: Tuesday, July 14, 2026 3:13 PM
> To: Shenwei Wang (OSS) <shenwei.wang@oss.nxp.com>
> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>; Linus Walleij
> <linusw@kernel.org>; Bartosz Golaszewski <brgl@kernel.org>; Jonathan Corbet
> <corbet@lwn.net>; Rob Herring <robh@kernel.org>; Krzysztof Kozlowski
> <krzk+dt@kernel.org>; Conor Dooley <conor+dt@kernel.org>; Bjorn Andersson
> <andersson@kernel.org>; Frank Li <frank.li@nxp.com>; Sascha Hauer
> <s.hauer@pengutronix.de>; Shuah Khan <skhan@linuxfoundation.org>; linux-
> gpio@vger.kernel.org; linux-doc@vger.kernel.org; linux-kernel@vger.kernel.org;
> Pengutronix Kernel Team <kernel@pengutronix.de>; Fabio Estevam
> <festevam@gmail.com>; Shenwei Wang <shenwei.wang@nxp.com>; Peng Fan
> <peng.fan@nxp.com>; devicetree@vger.kernel.org; linux-
> remoteproc@vger.kernel.org; imx@lists.linux.dev; linux-arm-
> kernel@lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>; Arnaud
> POULIQUEN <arnaud.pouliquen@foss.st.com>; b-padhi@ti.com
> Subject: Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg
> bus
> 
> > > 1) You did not include messages that mask and unmask interrupts at
> > > the driver side.
> >
> > Interrupt masking and unmasking are handled entirely on the local processor.
> >
> > When an interrupt occurs, the remote system masks the interrupt and
> > then sends a notification to Linux. After Linux processes the
> > notification, it sends a SET_IRQ_TYPE message back to the remote system,
> which then unmasks the interrupt.
> 
> Masking and unmasking an interrupt are orthogonal to the interrupt type.
> 
> When the interrupt fires, the interrupt core calls the irq_mask() operation on the
> interrupt. That should mask the interrupt. Once the handler has finished, the
> interrupt core, will call irq_unmask() to unmask the interrupt.
> 
> Edge, level, high, low, raising, falling has nothing to do with masking. Please don't
> mix concepts which Linux keeps separate.
> 

That's how virtio-gpio is implemented. It uses a single command (MSG_IRQ_TYPE, 0x6) for 
IRQ-related configuration, including masking, unmasking, and trigger type settings. Please 
refer to gpio-virtio.c for the details.

Shenwei

> 	 Andrew

^ permalink raw reply

* Re: [PATCH v14 1/5] docs: driver-api: gpio: rpmsg gpio driver over rpmsg bus
From: Andrew Lunn @ 2026-07-14 20:22 UTC (permalink / raw)
  To: Shenwei Wang (OSS)
  Cc: Mathieu Poirier, Linus Walleij, Bartosz Golaszewski,
	Jonathan Corbet, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Frank Li, Sascha Hauer, Shuah Khan,
	linux-gpio@vger.kernel.org, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, Pengutronix Kernel Team,
	Fabio Estevam, Shenwei Wang, Peng Fan, devicetree@vger.kernel.org,
	linux-remoteproc@vger.kernel.org, imx@lists.linux.dev,
	linux-arm-kernel@lists.infradead.org, dl-linux-imx,
	Arnaud POULIQUEN, b-padhi@ti.com
In-Reply-To: <PAXPR04MB918568AE7B2364EC9D16427689F92@PAXPR04MB9185.eurprd04.prod.outlook.com>

> The two fields above are required for rpmsg-gpio, but not for virtio-gpio.
> 
> In the rpmsg-gpio case, interrupt detection and handling occur on the remote processor. The 
> interrupt information (such as the GPIO line and trigger type) must therefore be sent to Linux 
> through this notification message.
> 
> In contrast, for virtio-gpio, interrupt handling is performed on the local processor. Since Linux already 
> has all the necessary interrupt context, the information is not needed.

Are you sure about that?

virtio_gpio_irq_set_type() sets:

        irq_line->type = type;
        irq_line->update_pending = true;

virtio_gpio_irq_bus_sync_unlock() looks at update_pending and does
virtio_gpio_req(), passing irq_line->type as type.

This then gets filled into:

/* Virtio GPIO Request / Response */
struct virtio_gpio_request {
	__le16 type;
	__le16 gpio;
	__le32 value;
};

which gets scatter/gathered over the virtqueue to the peer.

      Andrew

^ permalink raw reply

* [PATCH 4/4] fixup! drm/gpusvm: use hmm_range_fault_unlocked_timeout() for range faults
From: Stanislav Kinsburskii @ 2026-07-14 20:13 UTC (permalink / raw)
  To: airlied, akhilesh, akpm, corbet, dakr, david, jgg, kees, leon,
	liam, lizhi.hou, ljs, lyude, maarten.lankhorst, mamin506, mhocko,
	mripard, nouveau, ogabbay, oleg, rppt, shuah, simona, skhan,
	skinsburskii, surenb, tzimmermann, vbabka
  Cc: dri-devel, linux-mm, linux-doc, linux-kernel, linux-kselftest,
	linux-rdma
In-Reply-To: <178405975214.1082778.5193079941156341151.stgit@skinsburskii>

The timeout passed to hmm_range_fault_unlocked_timeout() is a relative
retry budget for HMM's internal mmu-notifier retry loop. drm_gpusvm was
still keeping an absolute deadline around the outer driver retry logic
and passing the remaining time into HMM.

Pass HMM_RANGE_DEFAULT_TIMEOUT directly to
hmm_range_fault_unlocked_timeout() on each HMM fault attempt instead.
If HMM succeeds but the later drm_gpusvm-side mmu_interval_read_retry()
check observes an invalidation, retry with a fresh HMM retry budget.

This keeps the timeout focused on repeated notifier retries inside HMM,
while avoiding an outer deadline that also accounts unrelated driver-side
work after HMM has made progress.

Signed-off-by: Stanislav Kinsburskii <skinsburskii@gmail.com>
---
 drivers/gpu/drm/drm_gpusvm.c |   21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c
index b8f2dd9982f5..76e8a0028c7f 100644
--- a/drivers/gpu/drm/drm_gpusvm.c
+++ b/drivers/gpu/drm/drm_gpusvm.c
@@ -852,8 +852,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
 		.end = end,
 		.dev_private_owner = dev_private_owner,
 	};
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	enum drm_gpusvm_scan_result state = DRM_GPUSVM_SCAN_UNPOPULATED, new_state;
 	unsigned long *pfns;
 	unsigned long npages = npages_in_range(start, end);
@@ -867,8 +866,7 @@ enum drm_gpusvm_scan_result drm_gpusvm_scan_mm(struct drm_gpusvm_range *range,
 	hmm_range.hmm_pfns = pfns;
 
 retry:
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-					       max(timeout - jiffies, 1L));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 	if (err)
 		goto err_free;
 
@@ -1459,8 +1457,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 		.dev_private_owner = ctx->device_private_page_owner,
 	};
 	void *zdd;
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	unsigned long i, j;
 	unsigned long npages = npages_in_range(pages_start, pages_end);
 	unsigned long num_dma_mapped;
@@ -1478,9 +1475,6 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 		return -EINVAL;
 
 retry:
-	if (time_after(jiffies, timeout))
-		return -EBUSY;
-
 	hmm_range.notifier_seq = mmu_interval_read_begin(notifier);
 	if (drm_gpusvm_pages_valid_unlocked(gpusvm, svm_pages))
 		goto set_seqno;
@@ -1495,8 +1489,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm,
 	}
 
 	hmm_range.hmm_pfns = pfns;
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-				max_t(long, timeout - jiffies, 1));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 	mmput(mm);
 	if (err)
 		goto err_free;
@@ -1718,8 +1711,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
 		.end = drm_gpusvm_range_end(range),
 		.dev_private_owner = NULL,
 	};
-	unsigned long timeout =
-		jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
+	unsigned long timeout = msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT);
 	unsigned long *pfns;
 	unsigned long npages = npages_in_range(drm_gpusvm_range_start(range),
 					       drm_gpusvm_range_end(range));
@@ -1734,8 +1726,7 @@ int drm_gpusvm_range_evict(struct drm_gpusvm *gpusvm,
 		return -ENOMEM;
 
 	hmm_range.hmm_pfns = pfns;
-	err = hmm_range_fault_unlocked_timeout(&hmm_range,
-				max_t(long, timeout - jiffies, 1));
+	err = hmm_range_fault_unlocked_timeout(&hmm_range, timeout);
 
 	kvfree(pfns);
 	mmput(mm);



^ 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