* Re: [PATCH 07/10] clk: amlogic: Support POWER_OF_TWO for PLL pre-divider
From: Jerome Brunet @ 2026-05-26 12:27 UTC (permalink / raw)
To: Jian Hu
Cc: Jian Hu via B4 Relay, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Neil Armstrong,
Xianwei Zhao, Kevin Hilman, Martin Blumenstingl, linux-kernel,
linux-clk, devicetree, linux-amlogic, linux-arm-kernel
In-Reply-To: <3fda1592-f7d0-4e86-8615-602804673414@amlogic.com>
On mar. 26 mai 2026 at 17:58, Jian Hu <jian.hu@amlogic.com> wrote:
> On 5/20/2026 3:35 PM, Jerome Brunet wrote:
>> [ EXTERNAL EMAIL ]
>>
>> On mer. 20 mai 2026 at 13:47, Jian Hu <jian.hu@amlogic.com> wrote:
>>
>>> On 5/14/2026 11:11 PM, Jerome Brunet wrote:
>>>> [ EXTERNAL EMAIL ]
>>>>
>>>> On lun. 11 mai 2026 at 20:47, Jian Hu via B4 Relay <devnull+jian.hu.amlogic.com@kernel.org> wrote:
>>>>
>>>>> From: Jian Hu <jian.hu@amlogic.com>
>>>>>
>>>>> The A9 PLL pre-divider uses a division factor of 2^n to ensure a clock
>>>>> duty cycle of 50% after predivision.
>>>>>
>>>>> Add flag 'CLK_MESON_PLL_N_POWER_OF_TWO' to indicate that the PLL
>>>>> pre-divider division factor is 2^n.
>>>> I understand what you are doing here but I have to ask why this can't be
>>>> implemented with independent dividers that already supports power of 2 ?
>>>
>>> If we use independent dividers, the n member would have to be removed from
>>> meson_clk_pll_data.
>>>
>>> However, n is referenced 35 times in clk-pll.c, which means we would need
>>> to modify all
>>> related logic across the file. This would be a relatively large
>>> change.
>> Yes
>>
>>>
>>> Moreover, for all Amlogic chips, the n divider is an indispensable part of
>>> the DCO clock.
>> There is hardly a justification here
>>
>>> The difference between SoC generations is as follows:
>>> Previous SoCs PLL: n = 1, 2, 3, 4... (linear divider)
>>> A9 SoC PLL: n = 2^0, 2^1, 2^2, 2^3, 2^4... (power-of-two
>>> divider)
>> Yes that was fairly obvious
>>
>>> Therefore, splitting out the n divider from the DCO clock might not be a
>>> good design choice.
>> I'm not sure I agree and you've only stated your point of view without
>> providing any technical justification here.
>>
>> From the datasheets of the different SoC we have, the documented
>> limitation is always the DCO output rate range. Nothing related to n (or
>> m, or the mult-range for that matter). This is a legacy problem, we
>> started with monolithic driver and slowly simplified it.
>>
>> As far as I can see now, reworking the PLL driver to be a simple
>> multiplier driver with range output rate constraint could actually be
>> simpler than the current code. I would also make simpler to accomodate
>> differences such as the one presented here.
>>
>> Unless you can provide technical reasons why going in this direction
>> would be incorrect, that's where I'd prefer to go.
>>
>>> [...]
>>>
>>> Best regards,
>>>
>>> Jian
>> --
>> Jerome
>
>
> I agree that having an independent N divider would simplify the PLL rate
> calculation.
>
> A separate pre-divider for N is technically possible, but there are some
> hardware constraints that need to be considered:
>
> N = 1 is the preferred operating mode except a few fixed-frequency PLLs.
> Larger N values reduce the PLL phase detector frequency, which may
> negatively impact
> jitter performance and overall PLL stability.
Understood. You could really make a difference by going deeper and
explaining what those constraints are, especially since you ask question
internally at Amlogic.
At the moment what is documented is a range regarding the output rate of
the PLLs. A PLL is made of a pre-divider and fractional multiplier.
and you are saying that for the multiplier to work and lock, there is
actually a constraint the input rate too.
If you can discuss with your HW team and clarify what the constraints
really are, that would help to better model the PLL. In then more likely
for us to figure out the best way to drive it.
>
> Because of this, we cannot guarantee stable system operation when arbitrary
> larger
> N values are used.
>
> Some PLLs require non-1 N values to generate specific fixed output
> frequencies because
> the target rate cannot be achieved with N = 1 while keeping the PLL while
> keeping the
> PLL within its valid operating range. So N is designed to have other values
> to
> satisfy this requirement.
Again it seems like the constraints we are using are not the real
limitation, just by-products, which the situation unclear.
>
> For example, the AXG PCIe PLL uses N = 3 to generate the required 100 MHz
> output frequency,
> since the target frequency cannot be achieved with N = 1.
>
PCIe is a topic in itself. It uses different ops for historic reasons though
I suspect, with proper constraints, it would not really need to.
>
> Additionally, is the refactored pre-divider N implemented as a separate
> patchset,
> independent from the A9 PLL changes?
I could be seen as a pre-requisite.
>
>
> Best regards,
>
>
> Jian
--
Jerome
^ permalink raw reply
* Re: [PATCH] arm64: mm: call pagetable dtor when freeing hot-removed page tables
From: David Hildenbrand (Arm) @ 2026-05-26 12:31 UTC (permalink / raw)
To: Kevin Brodsky, Vishal Moola, Catalin Marinas
Cc: Andrew Morton, Alistair Popple, linux-arm-kernel, linux-kernel,
linux-mm, will
In-Reply-To: <92450154-e1ab-46e4-b23d-eaa59c9cdd3b@arm.com>
On 5/26/26 13:54, Kevin Brodsky wrote:
> On 22/05/2026 11:36, Vishal Moola wrote:
>>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>>> index 4c8959153ac4..9d42cbddce27 100644
>>> --- a/arch/arm64/mm/mmu.c
>>> +++ b/arch/arm64/mm/mmu.c
>>> @@ -1441,6 +1441,9 @@ static void free_hotplug_page_range(struct page *page, size_t size,
>>>
>>> static void free_hotplug_pgtable_page(struct page *page)
>>> {
>>> + if (folio_test_pgtable(page_folio(page)))
>> This should work.
>>
>>> + pagetable_dtor(page_ptdesc(page));
>>> +
>>> free_hotplug_page_range(page, PAGE_SIZE, NULL);
>> In the case we presumably have a page table page (ptdesc) at this
>> point, we should really be freeing it with pagetable_free() as well.
>
> Agreed, I think this is the right thing to do, something like:
>
> if (folio_test_pgtable(page_folio(page)))
> pagetable_dtor_free(page_ptdesc(page)); else
> free_hotplug_page_range(page, PAGE_SIZE, NULL);
That code pattern is wrong.
folio_test_pgtable() shouldn't exist.
In the future, something is either a pgtable or a folio, not both.
So check the type against the page, not the folio.
--
Cheers,
David
^ permalink raw reply
* Re: (subset) [PATCH v4 0/5] J722S SGMII support
From: Nishanth Menon @ 2026-05-26 11:52 UTC (permalink / raw)
To: Vignesh Raghavendra, Tero Kristo, Vinod Koul, Neil Armstrong,
Nora Schiffer
Cc: Nishanth Menon, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Siddharth Vadapalli, Roger Quadros,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, netdev,
devicetree, linux-kernel, linux-phy, linux-arm-kernel, linux
In-Reply-To: <cover.1775559102.git.nora.schiffer@ew.tq-group.com>
Hi Nora Schiffer,
On Tue, 07 Apr 2026 13:42:32 +0200, Nora Schiffer wrote:
> The J722S CPSW and SERDES are very similar to the variants found on the
> AM64, but they additionally support SGMII. Introduce new compatible
> strings for the J722S to add this support to the drivers.
>
> This is a prerequisite for the Single-Pair Ethernet interface of the
> TQ-Systems MBa67xx baseboard for the TQMa67xx SoM, which will be
> submitted separately.
>
> [...]
I have applied the following to branch ti-k3-dts-next on [1].
Thank you!
[5/5] arm64: dts: ti: k3-j722s-main: use J722S compatibles for WIZ, gmii-sel and CPSW3G
commit: 2bdc0ea4e7304f6aa7e87089609fd902d9de7a2d
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent up the chain during
the next merge window (or sooner if it is a relevant bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
--
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D
https://ti.com/opensource
^ permalink raw reply
* Re: [PATCH v3 2/2] drm/bridge: analogix_dp: Add support for optional data-lanes mapping
From: Damon Ding @ 2026-05-26 12:35 UTC (permalink / raw)
To: Luca Ceresoli, Marek Szyprowski
Cc: hjc, heiko, andy.yan, maarten.lankhorst, mripard, tzimmermann,
airlied, simona, robh, krzk+dt, conor+dt, andrzej.hajda,
neil.armstrong, rfoss, Laurent.pinchart, jonas, jernej.skrabec,
nicolas.frattaroli, cristian.ciocaltea, sebastian.reichel,
dmitry.baryshkov, dianders, dri-devel, devicetree,
linux-arm-kernel, linux-rockchip, linux-kernel
In-Reply-To: <177979727057.297330.10691183273720133245.b4-review@b4>
Hi Luca,
On 5/26/2026 8:07 PM, Luca Ceresoli wrote:
> On Mon, 25 May 2026 17:47:31 +0800, Damon Ding <damon.ding@rock-chips.com> wrote:
>
> Hello Damon,
>
>>
>> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> index 8cf6b73bceac..d53ab25bc57b 100644
>> --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
>> @@ -1234,6 +1234,59 @@ static const struct drm_bridge_funcs analogix_dp_bridge_funcs = {
>> [ ... skip 11 lines ... ]
>> + int ret, i;
>> +
>> + memcpy(video_info->lane_map, map, sizeof(map));
>> +
>> + num_lanes = drm_of_get_data_lanes_count_ep(dp->dev->of_node, 1, 0, 1,
>> + video_info->max_lane_count);
>
> Should num_lanes be > 4, the buffers could overflow. I realize it should
> not happen, but analogix_dp_dt_parse_pdata() can set max_lane_count from
> the device tree, so a bogus dtb could cause such overflow.
>
> Perhaps you should just (in a separate patch) error out in
> analogix_dp_dt_parse_pdata() to prevent this. And maybe even adding an
> BUG_ON(lane_count > 4) here.
>
> Otherwise LGTM.
>
Thank you for the review.
I think it would be a better idea to add a separate patch to validate
the max_link_rate and max_lane_count values for Exynos DP.
I checked the Exynos DP related DTS files:
- The maximum value of samsung,lane-count is 4
- The maximum value of samsung,link-rate is 0x0a, which corresponds to
the HBR lane rate.
Could Marek please help confirm if we can set these as the upper limits
for the checks?
Best regards,
Damon
^ permalink raw reply
* RE: [PATCH v2] iommu: Allow device driver to use its own PASID space for SVA
From: Joonwon Kang @ 2026-05-26 12:36 UTC (permalink / raw)
To: kevin.tian, jgg
Cc: Alexander.Grest, alexander.shishkin, amhetre, baolu.lu, bp,
dave.hansen, easwar.hariharan, hpa, iommu, jacob.jun.pan,
joonwonkang, joro, jpb, kas, kees, linux-arm-kernel, linux-kernel,
mingo, nicolinc, peterz, praan, robin.murphy, ryasuoka, smostafa,
sohil.mehta, tglx, will, x86, xin
In-Reply-To: <DM6PR11MB3690699A3178F1559D4BE1CA8C0B2@DM6PR11MB3690.namprd11.prod.outlook.com>
> > From: Joonwon Kang <joonwonkang@google.com>
> > Sent: Tuesday, May 26, 2026 2:58 PM
> >
> > > On Mon, May 25, 2026 at 03:29:24PM +0000, Joonwon Kang wrote:
> > >
> > > > Currently, the only known expected user of the new kAPI is our team.
> > Since
> > > > I test if the patch resolves our problem before sending it, I believe it
> > > > should be good enough. Do you mean more than our team by
> > "accompanied
> > > > users"?
> > >
> > > He means you cannot send patches like this that only serve OOT drivers
> > > to the mainline kernel.
> >
> > Hmm, it gets back to the chicken-and-egg problem. So, do you recommend
> > deferring the patch submission until we find a new in-tree user of the
> > new kAPI? I believe we will not make our module in-tree anytime soon.
> > Or, is it like I still can send the patch and get it reviewed although we
> > cannot merge it to the mainline?
> >
>
> It's not chicken-and-egg problem. Just always send them together.
>
> so let's wait until your module is ready for in-tree review...
Since adding a new kAPI has this limitation, what do you think about the
idea of adding a new boot parameter to enforce disabling ENQCMD at EL0 and
using the non-global PASID space in that case? This way, I guess we could
resolve our issue without having to wait until we have new in-tree users.
Do you think it should have the same limitation?
Thanks,
Joonwon Kang
^ permalink raw reply
* Re: [PATCH v2] iommu: Allow device driver to use its own PASID space for SVA
From: Jason Gunthorpe @ 2026-05-26 12:39 UTC (permalink / raw)
To: Joonwon Kang
Cc: kevin.tian, Alexander.Grest, alexander.shishkin, amhetre,
baolu.lu, bp, dave.hansen, easwar.hariharan, hpa, iommu,
jacob.jun.pan, joro, jpb, kas, kees, linux-arm-kernel,
linux-kernel, mingo, nicolinc, peterz, praan, robin.murphy,
ryasuoka, smostafa, sohil.mehta, tglx, will, x86, xin
In-Reply-To: <20260526123606.2488278-1-joonwonkang@google.com>
On Tue, May 26, 2026 at 12:36:06PM +0000, Joonwon Kang wrote:
> > > From: Joonwon Kang <joonwonkang@google.com>
> > > Sent: Tuesday, May 26, 2026 2:58 PM
> > >
> > > > On Mon, May 25, 2026 at 03:29:24PM +0000, Joonwon Kang wrote:
> > > >
> > > > > Currently, the only known expected user of the new kAPI is our team.
> > > Since
> > > > > I test if the patch resolves our problem before sending it, I believe it
> > > > > should be good enough. Do you mean more than our team by
> > > "accompanied
> > > > > users"?
> > > >
> > > > He means you cannot send patches like this that only serve OOT drivers
> > > > to the mainline kernel.
> > >
> > > Hmm, it gets back to the chicken-and-egg problem. So, do you recommend
> > > deferring the patch submission until we find a new in-tree user of the
> > > new kAPI? I believe we will not make our module in-tree anytime soon.
> > > Or, is it like I still can send the patch and get it reviewed although we
> > > cannot merge it to the mainline?
> > >
> >
> > It's not chicken-and-egg problem. Just always send them together.
> >
> > so let's wait until your module is ready for in-tree review...
>
> Since adding a new kAPI has this limitation, what do you think about the
> idea of adding a new boot parameter to enforce disabling ENQCMD at EL0 and
> using the non-global PASID space in that case? This way, I guess we could
> resolve our issue without having to wait until we have new in-tree users.
> Do you think it should have the same limitation?
No, you can't hack up the kernel for OOT drivers.
Jason
^ permalink raw reply
* Re: [PATCH] [net-next] net: dsa: netc: fix enetc dependencies
From: Arnd Bergmann @ 2026-05-26 12:39 UTC (permalink / raw)
To: Wei Fang, Arnd Bergmann, Claudiu Manoil, Clark Wang,
Christophe Leroy
Cc: Andrew Lunn, Vladimir Oltean, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, imx@lists.linux.dev, Netdev,
linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
linux-arm-kernel@lists.infradead.org
In-Reply-To: <DBBPR04MB7500D92831D793CDD1D562E2880B2@DBBPR04MB7500.eurprd04.prod.outlook.com>
On Tue, May 26, 2026, at 13:03, Wei Fang wrote:
>
> Thanks for fix this issue, I have sent a patch last Sunday.
> Link: https://lore.kernel.org/netdev/20260524070310.2429819-1-wei.fang@nxp.com/
>
> I think the solution should simply be to add
> "depends on NET_VENDOR_FREESCALE", right? The changes in
> enetc_mdio.h seem more like improvements to me.
Yes, the added dependency is sufficient. I removed the other
change only because that was intended as a workaround
for the same problem but was incorrect.
Arnd
^ permalink raw reply
* Re: [PATCH v2 2/3] ASoC: sunxi: sun4i-spdif: Resume device before kcontrol register access
From: Bui Duc Phuc @ 2026-05-26 12:16 UTC (permalink / raw)
To: wens
Cc: broonie, codekipper, jernej.skrabec, lgirdwood, linux-arm-kernel,
linux-kernel, linux-sound, linux-sunxi, nichen, perex, samuel,
tiwai
In-Reply-To: <CAGb2v65zK7iOce_UZ+_F=dWtKYFGZj-K4k45MewvDbhivXPH2A@mail.gmail.com>
Hi Chenyu,
> When you submit a patch, it is expected that you already tested it.
> If you only compile tested it, please remember to say so in the
> footer (or mark the patch as RFT) so that others can test for you
> and the maintainer knows the status.
>
> And if possible, provide a scheme to test it.
>
Thanks for the guidance.
I’ll clearly mention the test status next time.
>
> I can't say that it does. But since the only control that SPDIF gives
> is the IEC958 status, and that doesn't appear in the standard mixer apps,
> it's unlikely that a _user_ will trigger it. Plus the control was added
> after the basic structure of the driver was done, so there is definitely
> some possibility of a crash.
>
> But what you wrote in the commit message doesn't match the actual hardware
> behavior, like I wrote.
Thanks for the clarification.
I'll update the commit message to something like:
"The kcontrols may access hardware registers while the
device is runtime-suspended.
Ensure the device is resumed before touching the registers."
Best Regards,
Phuc
^ permalink raw reply
* Re: [PATCH 2/8] bpf: Recover arena kernel faults with scratch page
From: David Hildenbrand (Arm) @ 2026-05-26 12:45 UTC (permalink / raw)
To: Tejun Heo, David Vernet, Andrea Righi, Changwoo Min,
Alexei Starovoitov, Andrii Nakryiko, Daniel Borkmann,
Martin KaFai Lau, Kumar Kartikeya Dwivedi
Cc: Peter Zijlstra, Catalin Marinas, Will Deacon, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, Andrew Morton,
Mike Rapoport, Emil Tsalapatis, sched-ext, bpf, x86,
linux-arm-kernel, linux-mm, linux-kernel
In-Reply-To: <20260522172219.1423324-3-tj@kernel.org>
On 5/22/26 19:22, Tejun Heo wrote:
> From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
>
> BPF arena usage is becoming more prevalent, but kernel <-> BPF communication
> over arena memory is awkward today. Data has to be staged through a trusted
> kernel pointer with extra code and copying on the BPF side. While reads
> through arena pointers can use a fault-safe helper, writes don't have a good
> solution. The in-line alternative would need instruction emulation or asm
> fixup labels.
>
> Enable direct kernel-side reads and writes within GUARD_SZ / 2 of any
> handed-in arena pointer, without bounds checking. A per-arena scratch page
> is installed by the arch fault path into empty arena kernel PTEs - x86 from
> page_fault_oops() for not-present faults, arm64 from __do_kernel_fault() for
> translation faults, both after the existing exception-table and KFENCE
> handling. The faulting instruction retries and the access is also reported
> through the program's BPF stream, preserving error reporting.
>
> bpf_prog_find_from_stack() resolves the current BPF program (and its arena)
> from the kernel stack - no new bpf_run_ctx state is added. Recovery covers
> the 4 GiB arena plus the upper half-guard (GUARD_SZ / 2). The lower
> half-guard is excluded because well-behaved kfuncs only access forward from
> arena pointers. The kfunc-author contract - access at most GUARD_SZ / 2 past
> a handed-in pointer - is documented in Documentation/bpf/kfuncs.rst.
>
> The install is lock-free via ptep_try_set(). On race-loss the winning
> installer's PTE is already valid, so the access retry succeeds. The arena
> clear path uses ptep_get_and_clear() so installer and clearer race through
> atomic accessors. No flush_tlb_kernel_range() afterwards. Stale "not mapped"
> entries just cause one extra re-fault, cheaper than a global IPI on every
> install.
>
> Scratch exists only to keep the kernel from oopsing on an in-line arena
> access. Its presence at a PTE means the BPF program has already
> malfunctioned, and the violation is reported through the program's BPF
> stream. The only requirement for behavior on a scratched PTE is that the
> kernel doesn't crash. In particular, any user-side access through such a PTE
> may segfault. The shared scratch page is freed once during map destruction.
>
> BPF instruction faults continue to use the existing JIT exception-table
> path. This patch changes only the kernel-text fault path. No UAPI flag is
> added. The new behavior is the default.
>
> v2: Use ptep_get_and_clear() in apply_range_clear_cb(). (David)
> v3: Stub bpf_arena_handle_page_fault() for !CONFIG_BPF_SYSCALL. (lkp)
>
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
> Cc: David Hildenbrand <david@kernel.org>
> ---
> Documentation/bpf/kfuncs.rst | 14 +++
> arch/arm64/mm/fault.c | 10 +-
> arch/x86/mm/fault.c | 12 ++-
> include/linux/bpf.h | 1 +
> include/linux/bpf_defs.h | 19 ++++
> kernel/bpf/arena.c | 177 +++++++++++++++++++++++++++--------
> kernel/bpf/core.c | 5 +
> 7 files changed, 191 insertions(+), 47 deletions(-)
> create mode 100644 include/linux/bpf_defs.h
>
> diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst
> index 75e6c078e0e7..6d497e720998 100644
> --- a/Documentation/bpf/kfuncs.rst
> +++ b/Documentation/bpf/kfuncs.rst
> @@ -462,6 +462,20 @@ In order to accommodate such requirements, the verifier will enforce strict
> PTR_TO_BTF_ID type matching if two types have the exact same name, with one
> being suffixed with ``___init``.
>
> +2.8 Accessing arena memory through kfunc arguments
> +--------------------------------------------------
> +
> +A read or write at any address inside an arena does not oops the kernel.
> +Unallocated arena pages are lazily backed by a scratch page and the
> +access is reported through the program's BPF stream as an error. Only
> +the BPF program's correctness is affected; the kernel itself remains
> +intact.
> +
> +The arena is followed by a ``GUARD_SZ / 2`` (32 KiB) guard region that
> +is also covered by this recovery. A kfunc handed an arena pointer may
> +therefore access up to ``GUARD_SZ / 2`` past it without bounds-checking
> +against the arena. Larger accesses must verify the range explicitly.
> +
> .. _BPF_kfunc_lifecycle_expectations:
>
> 3. kfunc lifecycle expectations
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 920a8b244d59..0d58d667fcd8 100644
> --- a/arch/arm64/mm/fault.c
> +++ b/arch/arm64/mm/fault.c
> @@ -9,6 +9,7 @@
>
> #include <linux/acpi.h>
> #include <linux/bitfield.h>
> +#include <linux/bpf_defs.h>
> #include <linux/extable.h>
> #include <linux/kfence.h>
> #include <linux/signal.h>
> @@ -416,9 +417,12 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
> } else if (addr < PAGE_SIZE) {
> msg = "NULL pointer dereference";
> } else {
> - if (esr_fsc_is_translation_fault(esr) &&
> - kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
> - return;
> + if (esr_fsc_is_translation_fault(esr)) {
> + if (kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
> + return;
> + if (bpf_arena_handle_page_fault(addr, esr & ESR_ELx_WNR, regs->pc))
> + return;
> + }
>
> msg = "paging request";
> }
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index f0e77e084482..b0f103ddbd23 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -8,6 +8,7 @@
> #include <linux/sched/task_stack.h> /* task_stack_*(), ... */
> #include <linux/kdebug.h> /* oops_begin/end, ... */
> #include <linux/memblock.h> /* max_low_pfn */
> +#include <linux/bpf_defs.h> /* bpf_arena_handle_page_fault */
> #include <linux/kfence.h> /* kfence_handle_page_fault */
> #include <linux/kprobes.h> /* NOKPROBE_SYMBOL, ... */
> #include <linux/mmiotrace.h> /* kmmio_handler, ... */
> @@ -688,10 +689,13 @@ page_fault_oops(struct pt_regs *regs, unsigned long error_code,
> if (IS_ENABLED(CONFIG_EFI))
> efi_crash_gracefully_on_page_fault(address);
>
> - /* Only not-present faults should be handled by KFENCE. */
> - if (!(error_code & X86_PF_PROT) &&
> - kfence_handle_page_fault(address, error_code & X86_PF_WRITE, regs))
> - return;
> + /* Only not-present faults should be handled by KFENCE or BPF arena. */
> + if (!(error_code & X86_PF_PROT)) {
> + if (kfence_handle_page_fault(address, error_code & X86_PF_WRITE, regs))
> + return;
> + if (bpf_arena_handle_page_fault(address, error_code & X86_PF_WRITE, regs->ip))
> + return;
> + }
>
> oops:
> /*
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 0136a108d083..831996c411cf 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -6,6 +6,7 @@
>
> #include <uapi/linux/bpf.h>
> #include <uapi/linux/filter.h>
> +#include <linux/bpf_defs.h>
>
> #include <crypto/sha2.h>
> #include <linux/workqueue.h>
> diff --git a/include/linux/bpf_defs.h b/include/linux/bpf_defs.h
> new file mode 100644
> index 000000000000..2185cd3966d4
> --- /dev/null
> +++ b/include/linux/bpf_defs.h
> @@ -0,0 +1,19 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Subset of bpf.h declarations, split out so files that need only these
> + * declarations can avoid bpf.h's full include cost.
> + */
> +#ifndef _LINUX_BPF_DEFS_H
> +#define _LINUX_BPF_DEFS_H
> +
> +#ifdef CONFIG_BPF_SYSCALL
> +bool bpf_arena_handle_page_fault(unsigned long addr, bool is_write, unsigned long fault_ip);
> +#else
> +static inline bool bpf_arena_handle_page_fault(unsigned long addr, bool is_write,
> + unsigned long fault_ip)
> +{
> + return false;
> +}
> +#endif
> +
> +#endif /* _LINUX_BPF_DEFS_H */
> diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
> index 08d008cc471e..1c0b87ecc817 100644
> --- a/kernel/bpf/arena.c
> +++ b/kernel/bpf/arena.c
> @@ -53,6 +53,7 @@ struct bpf_arena {
> u64 user_vm_start;
> u64 user_vm_end;
> struct vm_struct *kern_vm;
> + struct page *scratch_page;
> struct range_tree rt;
> /* protects rt */
> rqspinlock_t spinlock;
> @@ -118,6 +119,11 @@ struct apply_range_data {
> int i;
> };
>
> +struct clear_range_data {
> + struct llist_head *free_pages;
> + struct page *scratch_page;
> +};
> +
> static int apply_range_set_cb(pte_t *pte, unsigned long addr, void *data)
> {
> struct apply_range_data *d = data;
> @@ -144,33 +150,59 @@ static void flush_vmap_cache(unsigned long start, unsigned long size)
> flush_cache_vmap(start, start + size);
> }
There is still the chance that apply_range_set_cb() could race with scratch
insertion, right?
Shouldn't we also be using ptep_try_set() there?
The nasty thing is handling whether ptep_try_set() actually works.
Something like the following on top, maybe?
diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 49a8f7b1beef5..086bea3f3698e 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -122,19 +122,27 @@ static int apply_range_set_cb(pte_t *pte, unsigned long
addr, void *data)
{
struct apply_range_data *d = data;
struct page *page;
+ pte_t pteval;
if (!data)
return 0;
- /* sanity check */
- if (unlikely(!pte_none(ptep_get(pte))))
- return -EBUSY;
page = d->pages[d->i];
/* paranoia, similar to vmap_pages_pte_range() */
if (WARN_ON_ONCE(!pfn_valid(page_to_pfn(page))))
return -EINVAL;
- set_pte_at(&init_mm, addr, pte, mk_pte(page, PAGE_KERNEL));
+ pteval = mk_pte(page, PAGE_KERNEL);
+#ifdef ptep_try_set
+ if (unlikely(!ptep_try_set(pte, pteval)))
+ return -EBUSY;
+#else
+ if (unlikely(!pte_none(ptep_get(pte))))
+ return -EBUSY;
+
+ set_pte_at(&init_mm, addr, pte, pteval);
+#endif
d->i++;
return 0;
}
--
Cheers,
David
^ permalink raw reply related
* Re: [PATCH v2] iommu: Allow device driver to use its own PASID space for SVA
From: Joonwon Kang @ 2026-05-26 12:46 UTC (permalink / raw)
To: jgg
Cc: Alexander.Grest, alexander.shishkin, amhetre, baolu.lu, bp,
dave.hansen, easwar.hariharan, hpa, iommu, jacob.jun.pan,
joonwonkang, joro, jpb, kas, kees, kevin.tian, linux-arm-kernel,
linux-kernel, mingo, nicolinc, peterz, praan, robin.murphy,
ryasuoka, smostafa, sohil.mehta, tglx, will, x86, xin
In-Reply-To: <20260526123903.GF2487554@ziepe.ca>
> On Tue, May 26, 2026 at 12:36:06PM +0000, Joonwon Kang wrote:
> > > > From: Joonwon Kang <joonwonkang@google.com>
> > > > Sent: Tuesday, May 26, 2026 2:58 PM
> > > >
> > > > > On Mon, May 25, 2026 at 03:29:24PM +0000, Joonwon Kang wrote:
> > > > >
> > > > > > Currently, the only known expected user of the new kAPI is our team.
> > > > Since
> > > > > > I test if the patch resolves our problem before sending it, I believe it
> > > > > > should be good enough. Do you mean more than our team by
> > > > "accompanied
> > > > > > users"?
> > > > >
> > > > > He means you cannot send patches like this that only serve OOT drivers
> > > > > to the mainline kernel.
> > > >
> > > > Hmm, it gets back to the chicken-and-egg problem. So, do you recommend
> > > > deferring the patch submission until we find a new in-tree user of the
> > > > new kAPI? I believe we will not make our module in-tree anytime soon.
> > > > Or, is it like I still can send the patch and get it reviewed although we
> > > > cannot merge it to the mainline?
> > > >
> > >
> > > It's not chicken-and-egg problem. Just always send them together.
> > >
> > > so let's wait until your module is ready for in-tree review...
> >
> > Since adding a new kAPI has this limitation, what do you think about the
> > idea of adding a new boot parameter to enforce disabling ENQCMD at EL0 and
> > using the non-global PASID space in that case? This way, I guess we could
> > resolve our issue without having to wait until we have new in-tree users.
> > Do you think it should have the same limitation?
>
> No, you can't hack up the kernel for OOT drivers.
Alright, thanks for the confirmation.
Thanks,
Joonwon Kang
^ permalink raw reply
* Re: [PATCH v10 02/30] arm64/fpsimd: Update FA64 and ZT0 enables when loading SME state
From: Mark Rutland @ 2026-05-26 12:48 UTC (permalink / raw)
To: Mark Brown
Cc: Marc Zyngier, Joey Gouly, Catalin Marinas, Suzuki K Poulose,
Will Deacon, Paolo Bonzini, Jonathan Corbet, Shuah Khan,
Oliver Upton, Dave Martin, Fuad Tabba, Ben Horgan,
linux-arm-kernel, kvmarm, linux-kernel, kvm, linux-doc,
linux-kselftest, Peter Maydell, Eric Auger
In-Reply-To: <20260306-kvm-arm64-sme-v10-2-43f7683a0fb7@kernel.org>
On Fri, Mar 06, 2026 at 05:00:54PM +0000, Mark Brown wrote:
> Currently we enable EL0 and EL1 access to FA64 and ZT0 at boot and leave
> them enabled throughout the runtime of the system. When we add KVM support
> we will need to make this configuration dynamic, these features may be
> disabled for some KVM guests. Since the host kernel saves the floating
> point state for non-protected guests and we wish to avoid KVM having to
> reload the floating point state needlessly on guest reentry let's move the
> configuration of these enables to the floating point state reload.
>
> We provide a helper which does the configuration as part of a
> read/modify/write operation along with the configuration of the task VL,
> then update the floating point state load and SME access trap to use it.
> We also remove the setting of the enable bits from the CPU feature
> identification and resume paths. There will be a small overhead from
> setting the enables one at a time but this should be negligible in the
> context of the state load or access trap. In order to avoid compiler
> warnings due to unused variables in !CONFIG_ARM64_SME cases we avoid
> storing the vector length in temporary variables.
>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/include/asm/fpsimd.h | 18 ++++++++++++++++
> arch/arm64/kernel/cpufeature.c | 2 --
> arch/arm64/kernel/fpsimd.c | 47 +++++++++++------------------------------
> 3 files changed, 30 insertions(+), 37 deletions(-)
>
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index 1d2e33559bd5..7361b3b4a5f5 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -428,6 +428,22 @@ static inline size_t sme_state_size(struct task_struct const *task)
> return __sme_state_size(task_get_sme_vl(task));
> }
>
> +/*
> + * Note that unlike SVE we have additional feature bits for FA64 and
> + * ZT0 as well as the VL.
> + */
> +#define sme_cond_update_smcr(vl, fa64, zt0, reg) \
> + do { \
> + u64 __old = read_sysreg_s((reg)); \
> + u64 __new = vl & SMCR_ELx_LEN_MASK; \
Nit: this isn't VL, it's VQ - 1.
If that value is bigger than SMCR_ELx_LEN_MASK to begin with, there's a
latent bug in the caller, and silently masking the value is just hiding the
problem.
> + if (fa64) \
> + __new |= SMCR_ELx_FA64; \
> + if (zt0) \
> + __new |= SMCR_ELx_EZT0; \
> + if (__old != __new) \
> + write_sysreg_s(__new, (reg)); \
> + } while (0)
> +
I'd strongly prefer that we make it the caller's responsiblity to track
all the bits within SMCR, rather than requiring each caller to pass a
bag of booleans.
Either we can store the full SMCR value in the task, or we can have
something like:
unsigned long __task_smcr(const struct task_struct *tsk)
{
unsigned long vq = sve_vq_from_vl(task_get_sme_vl(tsk));
unsigned long smcr = vq - 1;
if (system_supports_fa64())
smcr |= SMCR_ELx_FA64;
if (system_supports_sme2())
smcr |= SMCR_ELx_EZT0;
return smcr;
}
... and if we need a helper for a conditional update, we can have
generic versions:
#define sysreg_cond_update(sysreg, val) \
sysreg_clear_set(syreg, ~0UL, val)
#define sysreg_cond_update_s(sysreg, val) \
sysreg_clear_set_s(syreg, ~0UL, val)
That way task_fpsimd_load() and do_sme_acc() don't need to duplicate all
the system_supports_XXX() checks, and both can have:
sysreg_cond_update_s(SYS_SMCR_EL1, __task_smcr(current));
... which keeps all the points of use simpler and consistent with one
another, and keeps the logic in the helper far more legibile and robust
(e.g. no macro variable shadowing).
We can do the same for ZCR, e.g.
unsigned long __task_zcr(const struct task_struct *tsk)
{
unsigned long vq = sve_vq_from_vl(task_get_sve_vl(tsk));
unsigned long zcr = vq - 1;
return zcr;
}
[...]
> diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
> index 9de1d8a604cb..cf419319f077 100644
> --- a/arch/arm64/kernel/fpsimd.c
> +++ b/arch/arm64/kernel/fpsimd.c
> @@ -398,11 +398,15 @@ static void task_fpsimd_load(void)
>
> /* Restore SME, override SVE register configuration if needed */
> if (system_supports_sme()) {
> - unsigned long sme_vl = task_get_sme_vl(current);
> -
> - /* Ensure VL is set up for restoring data */
> + /*
> + * Ensure VL is set up for restoring data. KVM might
> + * disable subfeatures so we reset them each time.
> + */
> if (test_thread_flag(TIF_SME))
> - sme_set_vq(sve_vq_from_vl(sme_vl) - 1);
> + sme_cond_update_smcr(sve_vq_from_vl(task_get_sme_vl(current)) - 1,
> + system_supports_fa64(),
> + system_supports_sme2(),
> + SYS_SMCR_EL1);
>
> write_sysreg_s(current->thread.svcr, SYS_SVCR);
With the proposal above, this would become:
if (system_supports_sme()) {
/*
* Ensure any SME controls are configured appropriately
* before restoring state.
*/
if (test_thread_flag(TIF_SME))
sysreg_cond_update_s(SYS_SMCR_EL1, __task_smcr(current));
[...]
}
[...]
> @@ -1400,9 +1376,10 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
> WARN_ON(1);
>
> if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
> - unsigned long vq_minus_one =
> - sve_vq_from_vl(task_get_sme_vl(current)) - 1;
> - sme_set_vq(vq_minus_one);
> + sme_cond_update_smcr(sve_vq_from_vl(task_get_sme_vl(current)) - 1,
> + system_supports_fa64(),
> + system_supports_sme2(),
> + SYS_SMCR_EL1);
>
> fpsimd_bind_task_to_cpu();
> } else {
Likewise, with the proposal above, this would become:
if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
sysreg_cond_update_s(SYS_SMCR_EL1, __task_smcr(current));
fpsimd_bind_task_to_cpu();
} else {
[...]
}
Mark.
^ permalink raw reply
* [PATCH v3] irqchip/gic-v4: Don't advertise VLPIs if no ITS is probed
From: Mostafa Saleh @ 2026-05-26 12:53 UTC (permalink / raw)
To: linux-arm-kernel, linux-kernel; +Cc: maz, tglx, Mostafa Saleh
When accidentally setting “kvm-arm.vgic_v4_enable=1” on the wrong
setup that has no MSI controller device tree node (it exists but
not used) and GICv4, it caused a panic as “gic_domain” is NULL and
the kernel attempted to access its ops.
Originally, I hit this on an older kernel, but was able to reproduce
it on upstream with Qemu by hacking this unreasonable setup.
[ 33.145536] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000028
[ 33.145658] Mem abort info:
[ 33.145751] ESR = 0x0000000096000006
...
[ 33.154057] CPU: 1 UID: 0 PID: 295 Comm: lkvm-static Not tainted 7.1.0-rc4-ge3f15ad3970e #5 PREEMPT
[ 33.156922] Hardware name: linux,dummy-virt (DT)
[ 33.158780] pstate: 81402005 (Nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[ 33.160340] pc : __irq_domain_instantiate+0x1d4/0x578
[ 33.162602] lr : __irq_domain_instantiate+0x1cc/0x578
Set vLPI support to false at init time if the host has no ITS, so it
propagates properly to kvm_vgic_global_state.has_gicv4.
Suggested-by: Marc Zyngier <maz@kernel.org>
Acked-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
v3: Reword subject based on Marc feedback.
v2: Fix the issue at construction as Marc suggested.
---
drivers/irqchip/irq-gic-v3-its.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 291d7668cc8d..d02cb9c17c0b 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -5837,6 +5837,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
its_acpi_probe();
if (list_empty(&its_nodes)) {
+ rdists->has_vlpis = false;
pr_warn("ITS: No ITS available, not enabling LPIs\n");
return -ENXIO;
}
--
2.54.0.746.g67dd491aae-goog
^ permalink raw reply related
* Re: [PATCH v10 03/30] arm64/fpsimd: Decide to save ZT0 and streaming mode FFR at bind time
From: Mark Rutland @ 2026-05-26 12:53 UTC (permalink / raw)
To: Mark Brown
Cc: Marc Zyngier, Joey Gouly, Catalin Marinas, Suzuki K Poulose,
Will Deacon, Paolo Bonzini, Jonathan Corbet, Shuah Khan,
Oliver Upton, Dave Martin, Fuad Tabba, Ben Horgan,
linux-arm-kernel, kvmarm, linux-kernel, kvm, linux-doc,
linux-kselftest, Peter Maydell, Eric Auger
In-Reply-To: <20260306-kvm-arm64-sme-v10-3-43f7683a0fb7@kernel.org>
On Fri, Mar 06, 2026 at 05:00:55PM +0000, Mark Brown wrote:
> Some parts of the SME state are optional, enabled by additional features
> on top of the base FEAT_SME and controlled with enable bits in SMCR_ELx. We
> unconditionally enable these for the host but for KVM we will allow the
> feature set exposed to guests to be restricted by the VMM. These are the
> FFR register (FEAT_SME_FA64) and ZT0 (FEAT_SME2).
>
> We defer saving of guest floating point state for non-protected guests to
> the host kernel. We also want to avoid having to reconfigure the guest
> floating point state if nothing used the floating point state while running
> the host. If the guest was running with the optional features disabled then
> traps will be enabled for them so the host kernel will need to skip
> accessing that state when saving state for the guest.
>
> Support this by moving the decision about saving this state to the point
> where we bind floating point state to the CPU, adding a new variable to
> the cpu_fp_state which uses the enable bits in SMCR_ELx to flag which
> features are enabled.
>
> Reviewed-by: Fuad Tabba <tabba@google.com>
> Signed-off-by: Mark Brown <broonie@kernel.org>
> ---
> arch/arm64/include/asm/fpsimd.h | 1 +
> arch/arm64/kernel/fpsimd.c | 10 ++++++++--
> arch/arm64/kvm/fpsimd.c | 1 +
> 3 files changed, 10 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
> index 7361b3b4a5f5..e97729aa3b2f 100644
> --- a/arch/arm64/include/asm/fpsimd.h
> +++ b/arch/arm64/include/asm/fpsimd.h
> @@ -87,6 +87,7 @@ struct cpu_fp_state {
> void *sme_state;
> u64 *svcr;
> u64 *fpmr;
> + u64 sme_features;
> unsigned int sve_vl;
> unsigned int sme_vl;
It would be simpler to store the full SMCR value, and remove the
'sme_vl' field. Likewise for ZCR and the 'sve_vl` field.
If nothing else, it would make the format of these fields more obvious,
and easier to reason about.
It would also potentially allow us to extend the VL sanity-check in
fpsimd_save_user_state() to check all the relevant control bits prior to
saving state.
[...]
> @@ -1632,6 +1632,12 @@ static void fpsimd_bind_task_to_cpu(void)
> last->to_save = FP_STATE_CURRENT;
> current->thread.fpsimd_cpu = smp_processor_id();
>
> + last->sme_features = 0;
> + if (system_supports_fa64())
> + last->sme_features |= SMCR_ELx_FA64;
> + if (system_supports_sme2())
> + last->sme_features |= SMCR_ELx_EZT0;
With my proposal on patch 2, this conditional logic would be
centralised within a helper function.
Mark.
^ permalink raw reply
* Re: [PATCH v10 04/30] arm64/fpsimd: Determine maximum virtualisable SME vector length
From: Mark Rutland @ 2026-05-26 12:55 UTC (permalink / raw)
To: Mark Brown
Cc: Marc Zyngier, Joey Gouly, Catalin Marinas, Suzuki K Poulose,
Will Deacon, Paolo Bonzini, Jonathan Corbet, Shuah Khan,
Oliver Upton, Dave Martin, Fuad Tabba, Ben Horgan,
linux-arm-kernel, kvmarm, linux-kernel, kvm, linux-doc,
linux-kselftest, Peter Maydell, Eric Auger
In-Reply-To: <agHOvFiI1e3y_ur4@sirena.co.uk>
On Mon, May 11, 2026 at 09:42:36PM +0900, Mark Brown wrote:
> On Mon, May 11, 2026 at 11:32:56AM +0100, Mark Rutland wrote:
> > On Fri, Mar 06, 2026 at 05:00:56PM +0000, Mark Brown wrote:
>
> > > +#define SME_VQ_INVALID (SME_VQ_MAX + 1)
>
> > Does using (SME_VQ_MAX + 1) for this make something easier than if we
> > used 0?
>
> There were checks for VLs less than $THING which were causing annoyance
> IIRC but it should be workable since we shouldn't offer SME to guests if
> the invalid VL comes up. I'll look again when I'm back from holiday.
>
> > To solve all of the above, I think what we actually want to do is find
> > the largest uniformly implemented VL which is smaller than the smallest
> > partially implemented VL.
>
> Yes, that's what we're going for.
To be clear, that was a concrete suggestiong as to the algorithm.
I'm saying we should have code along the lines of:
int find_virtualisable_vl(struct vl_info *info)
{
DECLARE_BITMAP(partial_only_map, SVE_VQ_MAX);
unsigned long b_min_partial, m_max_virt;
bitmap_andnot(partial_only_map, info->va_partial_map, info->vq_map,
SVE_VQ_MAX);
b_min_partial = find_last_bit(partial_only_map, SVE_VQ_MAX);
/* All implemented VLs are virtualisable */
if (m_min_partial >= SVE_VQ_MAX)
return info->max_vl;
b_max_virt = find_next_bit(info->vq_map, SVE_VQ_MAX, b_min_partial);
/* No implemented VLs are virtualisable */
if (b_max_virt >= SVE_VQ_MAX)
return 0;
/* At least one virtualisable VL exists */
return sve_vl_from_vq(__bit_to_vq(b_max_virt));
}
Mark.
^ permalink raw reply
* Re: [PATCH] arm64: tlb: Flush walk cache when unsharing PMD tables
From: Catalin Marinas @ 2026-05-26 13:01 UTC (permalink / raw)
To: Zeng Heng
Cc: will, akpm, npiggin, aneesh.kumar, peterz, linux-kernel,
wangkefeng.wang, linux-arm-kernel, linux-mm, linux-arch,
zengheng4, sunnanyong, blingxue
In-Reply-To: <f5b7460a-5719-bdb2-c53b-413468857f57@huaweicloud.com>
On Mon, May 25, 2026 at 05:20:14PM +0800, Zeng Heng wrote:
> On 2026/5/22 18:42, Catalin Marinas wrote:
> > On Thu, 21 May 2026 15:30:11 +0800, Zeng Heng wrote:
> > > When huge_pmd_unshare() is called to unshare a PMD table, the
> > > tlb_unshare_pmd_ptdesc() function sets tlb->unshared_tables=true
> > > but the aarch64 tlb_flush() only checked tlb->freed_tables to
> > > determine whether to use TLBF_NONE (vae1is, invalidates walk
> > > cache) or TLBF_NOWALKCACHE (vale1is, leaf-only).
> > >
> > > This caused the stale PMD page table entry to remain in the walk cache
> > > after unshare, potentially leading to incorrect page table walks.
> > >
> > > [...]
> > Applied to arm64 (for-next/fixes), thanks!
> >
> > [1/1] arm64: tlb: Flush walk cache when unsharing PMD tables
> > https://git.kernel.org/arm64/c/c2ff4764e03e
>
> This original issue was reported by our customer, who also participated
> in the root cause analysis and resolution.
>
> Could you please help add the below tags:
>
> Co-developed-by: Xue Xiaowei <blingxue@tencent.com>
> Signed-off-by: Xue Xiaowei <blingxue@tencent.com>
>
> Thank you in advance.
Too late unfortunately, the pull request went in on Friday. It will be
in the list archives though.
--
Catalin
^ permalink raw reply
* Re: [PATCH] KVM: arm64: Preserve all guest ZCR_EL2.LEN values
From: Mark Brown @ 2026-05-26 13:03 UTC (permalink / raw)
To: Mark Rutland
Cc: Marc Zyngier, Oliver Upton, Joey Gouly, Steffen Eiden,
Suzuki K Poulose, Catalin Marinas, Will Deacon, linux-arm-kernel,
kvmarm, linux-kernel
In-Reply-To: <ahWMByoIme6_oECX@J2N7QTR9R3>
[-- Attachment #1: Type: text/plain, Size: 1173 bytes --]
On Tue, May 26, 2026 at 01:03:19PM +0100, Mark Rutland wrote:
> On Tue, May 26, 2026 at 11:19:38AM +0100, Mark Brown wrote:
> The part I asked for clarification on was:
> AFAICT, none of the values for the SMCR_ELx.LEN and ZCR_ELx.LEN fields
> are reserved or unallocated. Thus all the bits of those fields should
> be stateful, and a read should observe the last value written,
> regardless of the effective value of the field.
> [...]
> Either what we're doing is wrong, or the architcture requires a
> clarification to say that values corresponding to unimplmented vector
> lengths are reserved.
...
> While one simple reading is that all values must be preserved exactly, I
> don't think this watertight, and I think while some people will take
> reading (a), others will take (b) or (c). I should have spelled that out
> more clearly in my initial mail, sorry.
I see. Given the general tendency to brevity it didn't occur to me that
options b or c might be a thing.
FWIW the restriction to powers of 2 was a revision in the architecture,
originally all values were allowed, though it's there now so the history
doesn't make a huge difference.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH v19 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski,
Dmitry Baryshkov, Konrad Dybcio
I feel like I fell into the trap of trying to address pre-existing
issues reported by sashiko and in the process provoking more reports so
let this be the last iteration where I do this. Vinod can we get this
queued for v7.2 now and iron out any previously existing problems in
tree?
Merging strategy: there are build-time dependencies between the crypto
and DMA patches so the best approach is for Vinod to create an immutable
branch with the DMA part pulled in by the crypto tree.
This iteration continues to build on top of v12 but uses the BAM's NWD
bit on data descriptors as suggested by Stephan. To that end, there are
some more changes like reversing the order of command and data
descriptors queuedy by the QCE driver.
Currently the QCE crypto driver accesses the crypto engine registers
directly via CPU. Trust Zone may perform crypto operations simultaneously
resulting in a race condition. To remedy that, let's introduce support
for BAM locking/unlocking to the driver. The BAM driver will now wrap
any existing issued descriptor chains with additional descriptors
performing the locking when the client starts the transaction
(dmaengine_issue_pending()). The client wanting to profit from locking
needs to switch to performing register I/O over DMA and communicate the
address to which to perform the dummy writes via a call to
dmaengine_desc_attach_metadata().
In the specific case of the BAM DMA this translates to sending command
descriptors performing dummy writes with the relevant flags set. The BAM
will then lock all other pipes not related to the current pipe group, and
keep handling the current pipe only until it sees the the unlock bit.
In order for the locking to work correctly, we also need to switch to
using DMA for all register I/O.
On top of this, the series contains some additional tweaks and
refactoring.
The goal of this is not to improve the performance but to prepare the
driver for supporting decryption into secure buffers in the future.
Tested with tcrypt.ko, kcapi and cryptsetup.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
Changes in v19:
- Fix more potential issues in remove path (sashiko)
- Remove unneeded return value check for vchan_tx_prep() as it can never
fail
- Link to v18: https://patch.msgid.link/20260522-qcom-qce-cmd-descr-v18-0-99103926bafc@oss.qualcomm.com
Changes in v18:
- Free the BAM interrupt before disabling the clock in remove() path too
- convert the size assigned to command descriptors to little endian
- don't pass DMA mapping attributes to dma_map_sg() in bam_dma when
setting up command descriptors
- Cancel the QCE workqueue *after* any outstanding DMA transfer
completes
- When mapping the scatterlist for command descriptors: use the actual
number of mapped segments for dmaengine_prep_slave_sg()
- Drop the leftover read_buf field from struct qce_device
- Unmap command descriptors only after terminating the RX transfer
- Pass the actual size of the metadata struct to
dmaengine_desc_attach_metadata(), this is not really required for our
use-case but let's do this for correctness and make sashiko happy
- Drop double assignment of bam_ce_idx in qce_clear_bam_transaction()
- Remove unused QCE_MAX_REG_READ
- Link to v17: https://patch.msgid.link/20260519-qcom-qce-cmd-descr-v17-0-53a595414b79@oss.qualcomm.com
Changes in v17:
- New patch: free the interrupt before disabling the clock in error path
in probe()
- New patch: cancel the QCE work on device detach
- Hold the channel lock when attaching the metadata
- Reorder the operations in devm_qce_dma_request() to avoid freeing
memory that may still be used by the DMA channel
- Register algorithms as the last step in QCE's probe() to avoid making
the resources available to the system before the DMA is fully set up
- Fix error paths in algo request handlers
- Don't pass dmaengine attributes to map_sg_attrs() as it expects
dma-mapping attribute flags
- Fix a dma mapping leak for command descriptors
- Rebase on top of v7.1-rc4
- Link to v16: https://patch.msgid.link/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc@oss.qualcomm.com
Changes in v16:
- Fix a reported race between dma_map_sg() called with spinlock taken
and the corresponding dma_unmap_sg() called without it by moving the
descriptor locking data into the descriptor struct
- Also queue the TX data descriptors before the command descriptors to
match what downstream is doing
- Tweak commit messages
- Rebase on top of v7.1-rc1
- Link to v15: https://patch.msgid.link/20260402-qcom-qce-cmd-descr-v15-0-98b5361f7ed7@oss.qualcomm.com
Changes in v15:
- Extend the descriptor metadata struct to also carry the channel's
transfer direction and stop using dmaengine_slave_config() for that
- Link to v14: https://patch.msgid.link/20260323-qcom-qce-cmd-descr-v14-0-f323af411274@oss.qualcomm.com
Changes in v14:
- Don't return an error to a client which wants to use locking on BAM
that doesn't support it
- Add a comment describing the DMA descriptor metadata structure
- Fix memory leaks
- Remove leftovers from previous iterations
- Propagate errors from dma_cookie_assign() when setting up lock
descriptors
- Link to v13: https://patch.msgid.link/20260317-qcom-qce-cmd-descr-v13-0-0968eb4f8c40@oss.qualcomm.com
Changes in v13:
- As part of the DMA changes in the QCE driver: reverse the order of
queueing the descriptors in the QCE driver: queue command descriptors
with all the register writes first, followed by all the data descriptors,
this is in line with the recommandations from the BAM HPG
- Set the NWD (notify-when-done) bit (DMA_PREP_FENCE in dmaengine
parlance) on the data descriptors to ensure that the UNLOCK descriptor
will not be processed until after they have been processed by the
engine. While technically the NWD bit is only needed on the final data
descriptor, it's hard to tell which one *will* be the last from the
driver's point-of-view and both the downstream driver as well as
the Qualcomm TZ against which we want to synchronize sets NWD on every
data descriptor,
- Revert to creating the LOCK/UNLOCK command descriptor pair in one
place now that the NWD bit is in place,
- Link to v12: https://patch.msgid.link/20260310-qcom-qce-cmd-descr-v12-0-398f37f26ef0@oss.qualcomm.com
Changes in v12:
- Wait until the transaction is done before queueing the UNLOCK command
descriptor
- Use descriptor metadata for communicating the scratchpad address to
the BAM driver
- To that end: reverse the order of the series (first BAM, then QCE) to
maintain bisectability
- Unmap buffers used for dummy writes after the transaction
- Link to v11: https://patch.msgid.link/20260302-qcom-qce-cmd-descr-v11-0-4bf1f5db4802@oss.qualcomm.com
Changes in v11:
- Use new approach, not requiring the client to be involved in locking.
- Add a patch constifying dma_descriptor_metadata_ops
- Rebase on top of v7.0-rc1
- Link to v10: https://lore.kernel.org/r/20251219-qcom-qce-cmd-descr-v10-0-ff7e4bf7dad4@oss.qualcomm.com
Changes in v10:
- Move DESC_FLAG_(UN)LOCK BIT definitions from patch 2 to 3
- Add a patch constifying the dma engine metadata as the first in the
series
- Use the VERSION register for dummy lock/unlock writes
- Link to v9: https://lore.kernel.org/r/20251128-qcom-qce-cmd-descr-v9-0-9a5f72b89722@linaro.org
Changes in v9:
- Drop the global, generic LOCK/UNLOCK flags and instead use DMA
descriptor metadata ops to pass BAM-specific information from the QCE
to the DMA engine
- Link to v8: https://lore.kernel.org/r/20251106-qcom-qce-cmd-descr-v8-0-ecddca23ca26@linaro.org
Changes in v8:
- Rework the command descriptor logic and drop a lot of unneeded code
- Use the physical address for BAM command descriptor access, not the
mapped DMA address
- Fix the problems with iommu faults on newer platforms
- Generalize the LOCK/UNLOCK flags in dmaengine and reword the docs and
commit messages
- Make the BAM locking logic stricter in the DMA engine driver
- Add some additional minor QCE driver refactoring changes to the series
- Lots of small reworks and tweaks to rebase on current mainline and fix
previous issues
- Link to v7: https://lore.kernel.org/all/20250311-qce-cmd-descr-v7-0-db613f5d9c9f@linaro.org/
Changes in v7:
- remove unused code: writing to multiple registers was not used in v6,
neither were the functions for reading registers over BAM DMA-
- remove
- don't read the SW_VERSION register needlessly in the BAM driver,
instead: encode the information on whether the IP supports BAM locking
in device match data
- shrink code where possible with logic modifications (for instance:
change the implementation of qce_write() instead of replacing it
everywhere with a new symbol)
- remove duplicated error messages
- rework commit messages
- a lot of shuffling code around for easier review and a more
streamlined series
- Link to v6: https://lore.kernel.org/all/20250115103004.3350561-1-quic_mdalam@quicinc.com/
Changes in v6:
- change "BAM" to "DMA"
- Ensured this series is compilable with the current Linux-next tip of
the tree (TOT).
Changes in v5:
- Added DMA_PREP_LOCK and DMA_PREP_UNLOCK flag support in separate patch
- Removed DMA_PREP_LOCK & DMA_PREP_UNLOCK flag
- Added FIELD_GET and GENMASK macro to extract major and minor version
Changes in v4:
- Added feature description and test hardware
with test command
- Fixed patch version numbering
- Dropped dt-binding patch
- Dropped device tree changes
- Added BAM_SW_VERSION register read
- Handled the error path for the api dma_map_resource()
in probe
- updated the commit messages for batter redability
- Squash the change where qce_bam_acquire_lock() and
qce_bam_release_lock() api got introduce to the change where
the lock/unlock flag get introced
- changed cover letter subject heading to
"dmaengine: qcom: bam_dma: add cmd descriptor support"
- Added the very initial post for BAM lock/unlock patch link
as v1 to track this feature
Changes in v3:
- https://lore.kernel.org/lkml/183d4f5e-e00a-8ef6-a589-f5704bc83d4a@quicinc.com/
- Addressed all the comments from v2
- Added the dt-binding
- Fix alignment issue
- Removed type casting from qce_write_reg_dma()
and qce_read_reg_dma()
- Removed qce_bam_txn = dma->qce_bam_txn; line from
qce_alloc_bam_txn() api and directly returning
dma->qce_bam_txn
Changes in v2:
- https://lore.kernel.org/lkml/20231214114239.2635325-1-quic_mdalam@quicinc.com/
- Initial set of patches for cmd descriptor support
- Add client driver to use BAM lock/unlock feature
- Added register read/write via BAM in QCE Crypto driver
to use BAM lock/unlock feature
---
Bartosz Golaszewski (14):
dmaengine: constify struct dma_descriptor_metadata_ops
dmaengine: qcom: bam_dma: free interrupt before the clock in error path
dmaengine: qcom: bam_dma: convert tasklet to a BH workqueue
dmaengine: qcom: bam_dma: Extend the driver's device match data
dmaengine: qcom: bam_dma: Add pipe_lock_supported flag support
dmaengine: qcom: bam_dma: add support for BAM locking
crypto: qce - Cancel work on device detach
crypto: qce - Include algapi.h in the core.h header
crypto: qce - Remove unused ignore_buf
crypto: qce - Simplify arguments of devm_qce_dma_request()
crypto: qce - Use existing devres APIs in devm_qce_dma_request()
crypto: qce - Map crypto memory for DMA
crypto: qce - Add BAM DMA support for crypto register I/O
crypto: qce - Communicate the base physical address to the dmaengine
drivers/crypto/qce/aead.c | 10 +-
drivers/crypto/qce/common.c | 20 ++--
drivers/crypto/qce/core.c | 39 ++++++-
drivers/crypto/qce/core.h | 7 ++
drivers/crypto/qce/dma.c | 168 ++++++++++++++++++++++++-----
drivers/crypto/qce/dma.h | 11 +-
drivers/crypto/qce/sha.c | 10 +-
drivers/crypto/qce/skcipher.c | 10 +-
drivers/dma/qcom/bam_dma.c | 227 +++++++++++++++++++++++++++++++++------
drivers/dma/ti/k3-udma.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 2 +-
include/linux/dma/qcom_bam_dma.h | 14 +++
include/linux/dmaengine.h | 2 +-
13 files changed, 427 insertions(+), 95 deletions(-)
---
base-commit: def113ae602a35ab7a1dc42a6c43188e180287be
change-id: 20251103-qcom-qce-cmd-descr-c5e9b11fe609
Best regards,
--
Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
^ permalink raw reply
* [PATCH v19 01/14] dmaengine: constify struct dma_descriptor_metadata_ops
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
There's no reason for the instances of this struct to be modifiable.
Constify the pointer in struct dma_async_tx_descriptor and all drivers
currently using it.
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/dma/ti/k3-udma.c | 2 +-
drivers/dma/xilinx/xilinx_dma.c | 2 +-
include/linux/dmaengine.h | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index c964ebfcf3b68d86e4bbc9b62bad2212f0ce3ee9..8a2f235b669aaf084a6f7b3e6b23d06b04768608 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -3408,7 +3408,7 @@ static int udma_set_metadata_len(struct dma_async_tx_descriptor *desc,
return 0;
}
-static struct dma_descriptor_metadata_ops metadata_ops = {
+static const struct dma_descriptor_metadata_ops metadata_ops = {
.attach = udma_attach_metadata,
.get_ptr = udma_get_metadata_ptr,
.set_len = udma_set_metadata_len,
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 404235c1735384635597e88edc25c67c7d250647..165b11a7c776abc6a8d66d631e19da669644577d 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -653,7 +653,7 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx,
return seg->hw.app;
}
-static struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = {
+static const struct dma_descriptor_metadata_ops xilinx_dma_metadata_ops = {
.get_ptr = xilinx_dma_get_metadata_ptr,
};
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index b3d251c9734e95e1b75cf6763d4d2c3a1c6a9910..5244edb90e7e7510bf4460b6a74ee2a7f91c1ccc 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -623,7 +623,7 @@ struct dma_async_tx_descriptor {
void *callback_param;
struct dmaengine_unmap_data *unmap;
enum dma_desc_metadata_mode desc_metadata_mode;
- struct dma_descriptor_metadata_ops *metadata_ops;
+ const struct dma_descriptor_metadata_ops *metadata_ops;
#ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
struct dma_async_tx_descriptor *next;
struct dma_async_tx_descriptor *parent;
--
2.47.3
^ permalink raw reply related
* [PATCH v19 02/14] dmaengine: qcom: bam_dma: free interrupt before the clock in error path
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
The BAM interrupt is requested with a devres helper and so on error it's
freed after probe() returns. We disable the clock before freeing or
masking it so it may still fire and we may end up reading BAM registers
with clock disabled.
Stop using devres for interrupts as we free it in remove() manually
anyway. Add an appropriate label and free the interrupt before disabling
the clock in error path and in remove().
Fixes: e7c0fe2a5c84 ("dmaengine: add Qualcomm BAM dma driver")
Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=2
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/dma/qcom/bam_dma.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index 19116295f8325767a0d97a7848077885b118241c..b3d36ea79984385fe0d05ce56042d3e6e3030c5a 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -1302,8 +1302,7 @@ static int bam_dma_probe(struct platform_device *pdev)
for (i = 0; i < bdev->num_channels; i++)
bam_channel_init(bdev, &bdev->channels[i], i);
- ret = devm_request_irq(bdev->dev, bdev->irq, bam_dma_irq,
- IRQF_TRIGGER_HIGH, "bam_dma", bdev);
+ ret = request_irq(bdev->irq, bam_dma_irq, IRQF_TRIGGER_HIGH, "bam_dma", bdev);
if (ret)
goto err_bam_channel_exit;
@@ -1336,7 +1335,7 @@ static int bam_dma_probe(struct platform_device *pdev)
ret = dma_async_device_register(&bdev->common);
if (ret) {
dev_err(bdev->dev, "failed to register dma async device\n");
- goto err_bam_channel_exit;
+ goto err_free_irq;
}
ret = of_dma_controller_register(pdev->dev.of_node, bam_dma_xlate,
@@ -1355,6 +1354,8 @@ static int bam_dma_probe(struct platform_device *pdev)
err_unregister_dma:
dma_async_device_unregister(&bdev->common);
+err_free_irq:
+ free_irq(bdev->irq, bdev);
err_bam_channel_exit:
for (i = 0; i < bdev->num_channels; i++)
tasklet_kill(&bdev->channels[i].vc.task);
@@ -1371,6 +1372,8 @@ static void bam_dma_remove(struct platform_device *pdev)
struct bam_device *bdev = platform_get_drvdata(pdev);
u32 i;
+ free_irq(bdev->irq, bdev);
+
pm_runtime_force_suspend(&pdev->dev);
of_dma_controller_free(pdev->dev.of_node);
@@ -1379,8 +1382,6 @@ static void bam_dma_remove(struct platform_device *pdev)
/* mask all interrupts for this execution environment */
writel_relaxed(0, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
- devm_free_irq(bdev->dev, bdev->irq, bdev);
-
for (i = 0; i < bdev->num_channels; i++) {
bam_dma_terminate_all(&bdev->channels[i].vc.chan);
tasklet_kill(&bdev->channels[i].vc.task);
--
2.47.3
^ permalink raw reply related
* [PATCH v19 06/14] dmaengine: qcom: bam_dma: add support for BAM locking
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
Add support for BAM pipe locking. To that end: when starting DMA on an RX
channel - prepend the existing queue of issued descriptors with an
additional "dummy" command descriptor with the LOCK bit set. Once the
transaction is done (no more issued descriptors), issue one more dummy
descriptor with the UNLOCK bit.
We *must* wait until the transaction is signalled as done because we
must not perform any writes into config registers while the engine is
busy.
The dummy writes must be issued into a scratchpad register of the client
so provide a mechanism to communicate the right address via descriptor
metadata.
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/dma/qcom/bam_dma.c | 153 ++++++++++++++++++++++++++++++++++++++-
include/linux/dma/qcom_bam_dma.h | 14 ++++
2 files changed, 163 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
index 04fe1d546be73f074c66c4a5712ad65717e10929..84fd9e181bdd5fd9a4a744050ba57f05f54787c7 100644
--- a/drivers/dma/qcom/bam_dma.c
+++ b/drivers/dma/qcom/bam_dma.c
@@ -28,11 +28,13 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
+#include <linux/dma/qcom_bam_dma.h>
#include <linux/dmaengine.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_dma.h>
@@ -60,6 +62,8 @@ struct bam_desc_hw {
#define DESC_FLAG_EOB BIT(13)
#define DESC_FLAG_NWD BIT(12)
#define DESC_FLAG_CMD BIT(11)
+#define DESC_FLAG_LOCK BIT(10)
+#define DESC_FLAG_UNLOCK BIT(9)
struct bam_async_desc {
struct virt_dma_desc vd;
@@ -72,6 +76,10 @@ struct bam_async_desc {
struct bam_desc_hw *curr_desc;
+ /* BAM locking infrastructure */
+ struct scatterlist lock_sg;
+ struct bam_cmd_element lock_ce;
+
/* list node for the desc in the bam_chan list of descriptors */
struct list_head desc_node;
enum dma_transfer_direction dir;
@@ -391,6 +399,10 @@ struct bam_chan {
struct list_head desc_list;
struct list_head node;
+
+ /* BAM locking infrastructure */
+ phys_addr_t scratchpad_addr;
+ enum dma_transfer_direction direction;
};
static inline struct bam_chan *to_bam_chan(struct dma_chan *common)
@@ -652,6 +664,35 @@ static int bam_slave_config(struct dma_chan *chan,
return 0;
}
+static int bam_metadata_attach(struct dma_async_tx_descriptor *desc, void *data, size_t len)
+{
+ struct bam_chan *bchan = to_bam_chan(desc->chan);
+ const struct bam_device_data *bdata = bchan->bdev->dev_data;
+ struct bam_desc_metadata *metadata = data;
+
+ if (!data)
+ return -EINVAL;
+
+ if (!bdata->pipe_lock_supported)
+ /*
+ * The client wants to use locking but this BAM version doesn't
+ * support it. Don't return an error here as this will stop the
+ * client from using DMA at all for no reason.
+ */
+ return 0;
+
+ guard(spinlock_irqsave)(&bchan->vc.lock);
+
+ bchan->scratchpad_addr = metadata->scratchpad_addr;
+ bchan->direction = metadata->direction;
+
+ return 0;
+}
+
+static const struct dma_descriptor_metadata_ops bam_metadata_ops = {
+ .attach = bam_metadata_attach,
+};
+
/**
* bam_prep_slave_sg - Prep slave sg transaction
*
@@ -668,6 +709,7 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan,
void *context)
{
struct bam_chan *bchan = to_bam_chan(chan);
+ struct dma_async_tx_descriptor *tx_desc;
struct bam_device *bdev = bchan->bdev;
struct bam_async_desc *async_desc;
struct scatterlist *sg;
@@ -723,7 +765,10 @@ static struct dma_async_tx_descriptor *bam_prep_slave_sg(struct dma_chan *chan,
} while (remainder > 0);
}
- return vchan_tx_prep(&bchan->vc, &async_desc->vd, flags);
+ tx_desc = vchan_tx_prep(&bchan->vc, &async_desc->vd, flags);
+ tx_desc->metadata_ops = &bam_metadata_ops;
+
+ return tx_desc;
}
/**
@@ -1012,13 +1057,105 @@ static void bam_apply_new_config(struct bam_chan *bchan,
bchan->reconfigure = 0;
}
+static struct bam_async_desc *
+bam_make_lock_desc(struct bam_chan *bchan, unsigned long flag)
+{
+ struct dma_chan *chan = &bchan->vc.chan;
+ struct bam_async_desc *async_desc;
+ struct bam_desc_hw *desc;
+ struct virt_dma_desc *vd;
+ struct virt_dma_chan *vc;
+ unsigned int mapped;
+ dma_cookie_t cookie;
+ int ret;
+
+ async_desc = kzalloc_flex(*async_desc, desc, 1, GFP_NOWAIT);
+ if (!async_desc) {
+ dev_err(bchan->bdev->dev, "failed to allocate the BAM lock descriptor\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ sg_init_table(&async_desc->lock_sg, 1);
+
+ async_desc->num_desc = 1;
+ async_desc->curr_desc = async_desc->desc;
+ async_desc->dir = DMA_MEM_TO_DEV;
+
+ desc = async_desc->desc;
+
+ bam_prep_ce_le32(&async_desc->lock_ce, bchan->scratchpad_addr, BAM_WRITE_COMMAND, 0);
+ sg_set_buf(&async_desc->lock_sg, &async_desc->lock_ce, sizeof(async_desc->lock_ce));
+
+ mapped = dma_map_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE);
+ if (!mapped) {
+ kfree(async_desc);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ desc->flags |= cpu_to_le16(DESC_FLAG_CMD | flag);
+ desc->addr = sg_dma_address(&async_desc->lock_sg);
+ desc->size = cpu_to_le16(sizeof(struct bam_cmd_element));
+
+ vc = &bchan->vc;
+ vd = &async_desc->vd;
+
+ dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
+ vd->tx.flags = DMA_PREP_CMD;
+ vd->tx.desc_free = vchan_tx_desc_free;
+ vd->tx_result.result = DMA_TRANS_NOERROR;
+ vd->tx_result.residue = 0;
+
+ cookie = dma_cookie_assign(&vd->tx);
+ ret = dma_submit_error(cookie);
+ if (ret) {
+ dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE);
+ kfree(async_desc);
+ return ERR_PTR(ret);
+ }
+
+ return async_desc;
+}
+
+static int bam_do_setup_pipe_lock(struct bam_chan *bchan, bool lock)
+{
+ struct bam_device *bdev = bchan->bdev;
+ const struct bam_device_data *bdata = bdev->dev_data;
+ struct bam_async_desc *lock_desc;
+ unsigned long flag;
+
+ lockdep_assert_held(&bchan->vc.lock);
+
+ if (!bdata->pipe_lock_supported || !bchan->scratchpad_addr ||
+ bchan->direction != DMA_MEM_TO_DEV)
+ return 0;
+
+ flag = lock ? DESC_FLAG_LOCK : DESC_FLAG_UNLOCK;
+
+ lock_desc = bam_make_lock_desc(bchan, flag);
+ if (IS_ERR(lock_desc))
+ return PTR_ERR(lock_desc);
+
+ if (lock)
+ list_add(&lock_desc->vd.node, &bchan->vc.desc_issued);
+ else
+ list_add_tail(&lock_desc->vd.node, &bchan->vc.desc_issued);
+
+ return 0;
+}
+
+static void bam_setup_pipe_lock(struct bam_chan *bchan)
+{
+ if (bam_do_setup_pipe_lock(bchan, true) || bam_do_setup_pipe_lock(bchan, false))
+ dev_err(bchan->vc.chan.slave, "Failed to setup BAM pipe lock descriptors");
+}
+
/**
* bam_start_dma - start next transaction
* @bchan: bam dma channel
*/
static void bam_start_dma(struct bam_chan *bchan)
{
- struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc);
+ struct virt_dma_desc *vd;
struct bam_device *bdev = bchan->bdev;
struct bam_async_desc *async_desc = NULL;
struct bam_desc_hw *desc;
@@ -1030,6 +1167,9 @@ static void bam_start_dma(struct bam_chan *bchan)
lockdep_assert_held(&bchan->vc.lock);
+ bam_setup_pipe_lock(bchan);
+
+ vd = vchan_next_desc(&bchan->vc);
if (!vd)
return;
@@ -1157,8 +1297,12 @@ static void bam_issue_pending(struct dma_chan *chan)
*/
static void bam_dma_free_desc(struct virt_dma_desc *vd)
{
- struct bam_async_desc *async_desc = container_of(vd,
- struct bam_async_desc, vd);
+ struct bam_async_desc *async_desc = container_of(vd, struct bam_async_desc, vd);
+ struct bam_desc_hw *desc = async_desc->desc;
+ struct dma_chan *chan = vd->tx.chan;
+
+ if (le16_to_cpu(desc->flags) & (DESC_FLAG_LOCK | DESC_FLAG_UNLOCK))
+ dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE);
kfree(async_desc);
}
@@ -1349,6 +1493,7 @@ static int bam_dma_probe(struct platform_device *pdev)
bdev->common.device_terminate_all = bam_dma_terminate_all;
bdev->common.device_issue_pending = bam_issue_pending;
bdev->common.device_tx_status = bam_tx_status;
+ bdev->common.desc_metadata_modes = DESC_METADATA_CLIENT;
bdev->common.dev = bdev->dev;
ret = dma_async_device_register(&bdev->common);
diff --git a/include/linux/dma/qcom_bam_dma.h b/include/linux/dma/qcom_bam_dma.h
index 68fc0e643b1b97fe4520d5878daa322b81f4f559..a2594264b0f58c4b2b1c85e243cad0d5669c26dc 100644
--- a/include/linux/dma/qcom_bam_dma.h
+++ b/include/linux/dma/qcom_bam_dma.h
@@ -6,6 +6,8 @@
#ifndef _QCOM_BAM_DMA_H
#define _QCOM_BAM_DMA_H
+#include <linux/dmaengine.h>
+
#include <asm/byteorder.h>
/*
@@ -34,6 +36,18 @@ enum bam_command_type {
BAM_READ_COMMAND,
};
+/**
+ * struct bam_desc_metadata - DMA descriptor metadata specific to the BAM driver.
+ *
+ * @scratchpad_addr: Physical address to use for dummy write operations when
+ * queuing command descriptors with LOCK/UNLOCK bits set.
+ * @direction: Transfer direction of this channel.
+ */
+struct bam_desc_metadata {
+ phys_addr_t scratchpad_addr;
+ enum dma_transfer_direction direction;
+};
+
/*
* prep_bam_ce_le32 - Wrapper function to prepare a single BAM command
* element with the data already in le32 format.
--
2.47.3
^ permalink raw reply related
* [PATCH v19 08/14] crypto: qce - Include algapi.h in the core.h header
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
The header defines a struct embedding struct crypto_queue whose size
needs to be known and which is defined in crypto/algapi.h. Move the
inclusion from core.c to core.h.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/crypto/qce/core.c | 1 -
drivers/crypto/qce/core.h | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
index f671946cf7351cd5f0c319909bafd87e3af701c7..ad37c2b8ae53a373bb248aff06c3b7946e8439a8 100644
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -13,7 +13,6 @@
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/types.h>
-#include <crypto/algapi.h>
#include <crypto/internal/hash.h>
#include "core.h"
diff --git a/drivers/crypto/qce/core.h b/drivers/crypto/qce/core.h
index eb6fa7a8b64a81daf9ad5304a3ae4e5e597a70b8..f092ce2d3b04a936a37805c20ac5ba78d8fdd2df 100644
--- a/drivers/crypto/qce/core.h
+++ b/drivers/crypto/qce/core.h
@@ -8,6 +8,7 @@
#include <linux/mutex.h>
#include <linux/workqueue.h>
+#include <crypto/algapi.h>
#include "dma.h"
--
2.47.3
^ permalink raw reply related
* [PATCH v19 07/14] crypto: qce - Cancel work on device detach
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
The workqueue is setup in probe() but never cancelled on error or in
remove(). Set up a devres action to clean it up. We need to move the
initialization earlier as we don't want to cancel the work before any
outstanding DMA transfer is terminated. Make sure we do terminate all
transfers in qce_dma_release() devres action.
Fixes: eb7986e5e14d ("crypto: qce - convert tasklet to workqueue")
Closes: https://sashiko.dev/#/patchset/20260427-qcom-qce-cmd-descr-v16-0-945fd1cafbbc%40oss.qualcomm.com?part=7
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/crypto/qce/core.c | 13 ++++++++++++-
drivers/crypto/qce/dma.c | 2 ++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
index b966f3365b7de8d2a8f6707397a34aa4facdc4ac..f671946cf7351cd5f0c319909bafd87e3af701c7 100644
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -186,6 +186,13 @@ static int qce_check_version(struct qce_device *qce)
return 0;
}
+static void qce_cancel_work(void *data)
+{
+ struct work_struct *work = data;
+
+ cancel_work_sync(work);
+}
+
static int qce_crypto_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -227,6 +234,11 @@ static int qce_crypto_probe(struct platform_device *pdev)
if (ret)
return ret;
+ INIT_WORK(&qce->done_work, qce_req_done_work);
+ ret = devm_add_action_or_reset(dev, qce_cancel_work, &qce->done_work);
+ if (ret)
+ return ret;
+
ret = devm_qce_dma_request(qce->dev, &qce->dma);
if (ret)
return ret;
@@ -239,7 +251,6 @@ static int qce_crypto_probe(struct platform_device *pdev)
if (ret)
return ret;
- INIT_WORK(&qce->done_work, qce_req_done_work);
crypto_init_queue(&qce->queue, QCE_QUEUE_LENGTH);
qce->async_req_enqueue = qce_async_request_enqueue;
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
index 68cafd4741ad3d91906d39e817fc7873b028d498..7ec9d72fd690fb17e03ade7efe3cc522fb47e1ac 100644
--- a/drivers/crypto/qce/dma.c
+++ b/drivers/crypto/qce/dma.c
@@ -13,6 +13,8 @@ static void qce_dma_release(void *data)
{
struct qce_dma_data *dma = data;
+ dmaengine_terminate_sync(dma->txchan);
+ dmaengine_terminate_sync(dma->rxchan);
dma_release_channel(dma->txchan);
dma_release_channel(dma->rxchan);
kfree(dma->result_buf);
--
2.47.3
^ permalink raw reply related
* [PATCH v19 09/14] crypto: qce - Remove unused ignore_buf
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
It's unclear what the purpose of this field is. It has been here since
the initial commit but without any explanation. The driver works fine
without it. We still keep allocating more space in the result buffer, we
just don't need to store its address. While at it: move the
QCE_IGNORE_BUF_SZ definition into dma.c as it's not used outside of this
compilation unit.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/crypto/qce/dma.c | 4 ++--
drivers/crypto/qce/dma.h | 2 --
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
index 7ec9d72fd690fb17e03ade7efe3cc522fb47e1ac..d1daa229361aa74da5d3d7bfe1bc8ab189761e38 100644
--- a/drivers/crypto/qce/dma.c
+++ b/drivers/crypto/qce/dma.c
@@ -9,6 +9,8 @@
#include "dma.h"
+#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
+
static void qce_dma_release(void *data)
{
struct qce_dma_data *dma = data;
@@ -43,8 +45,6 @@ int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma)
goto error_nomem;
}
- dma->ignore_buf = dma->result_buf + QCE_RESULT_BUF_SZ;
-
return devm_add_action_or_reset(dev, qce_dma_release, dma);
error_nomem:
diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h
index 31629185000e12242fa07c2cc08b95fcbd5d4b8c..fc337c435cd14917bdfb99febcf9119275afdeba 100644
--- a/drivers/crypto/qce/dma.h
+++ b/drivers/crypto/qce/dma.h
@@ -23,7 +23,6 @@ struct qce_result_dump {
u32 status2;
};
-#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
#define QCE_RESULT_BUF_SZ \
ALIGN(sizeof(struct qce_result_dump), QCE_BAM_BURST_SIZE)
@@ -31,7 +30,6 @@ struct qce_dma_data {
struct dma_chan *txchan;
struct dma_chan *rxchan;
struct qce_result_dump *result_buf;
- void *ignore_buf;
};
int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma);
--
2.47.3
^ permalink raw reply related
* [PATCH v19 10/14] crypto: qce - Simplify arguments of devm_qce_dma_request()
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This function can extract all the information it needs from struct
qce_device alone so simplify its arguments. This is done in preparation
for adding support for register I/O over DMA which will require
accessing even more fields from struct qce_device.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/crypto/qce/core.c | 2 +-
drivers/crypto/qce/dma.c | 5 ++++-
drivers/crypto/qce/dma.h | 4 +++-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/crypto/qce/core.c b/drivers/crypto/qce/core.c
index ad37c2b8ae53a373bb248aff06c3b7946e8439a8..a0e2eadc3afd5f83e46724c8bc3e3690146b86ba 100644
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -238,7 +238,7 @@ static int qce_crypto_probe(struct platform_device *pdev)
if (ret)
return ret;
- ret = devm_qce_dma_request(qce->dev, &qce->dma);
+ ret = devm_qce_dma_request(qce);
if (ret)
return ret;
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
index d1daa229361aa74da5d3d7bfe1bc8ab189761e38..d60efb5c26d88f8b0259b1dccc8724d0f75571c6 100644
--- a/drivers/crypto/qce/dma.c
+++ b/drivers/crypto/qce/dma.c
@@ -7,6 +7,7 @@
#include <linux/dmaengine.h>
#include <crypto/scatterwalk.h>
+#include "core.h"
#include "dma.h"
#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
@@ -22,8 +23,10 @@ static void qce_dma_release(void *data)
kfree(dma->result_buf);
}
-int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma)
+int devm_qce_dma_request(struct qce_device *qce)
{
+ struct qce_dma_data *dma = &qce->dma;
+ struct device *dev = qce->dev;
int ret;
dma->txchan = dma_request_chan(dev, "tx");
diff --git a/drivers/crypto/qce/dma.h b/drivers/crypto/qce/dma.h
index fc337c435cd14917bdfb99febcf9119275afdeba..483789d9fa98e79d1283de8297bf2fc2a773f3a7 100644
--- a/drivers/crypto/qce/dma.h
+++ b/drivers/crypto/qce/dma.h
@@ -8,6 +8,8 @@
#include <linux/dmaengine.h>
+struct qce_device;
+
/* maximum data transfer block size between BAM and CE */
#define QCE_BAM_BURST_SIZE 64
@@ -32,7 +34,7 @@ struct qce_dma_data {
struct qce_result_dump *result_buf;
};
-int devm_qce_dma_request(struct device *dev, struct qce_dma_data *dma);
+int devm_qce_dma_request(struct qce_device *qce);
int qce_dma_prep_sgs(struct qce_dma_data *dma, struct scatterlist *sg_in,
int in_ents, struct scatterlist *sg_out, int out_ents,
dma_async_tx_callback cb, void *cb_param);
--
2.47.3
^ permalink raw reply related
* [PATCH v19 11/14] crypto: qce - Use existing devres APIs in devm_qce_dma_request()
From: Bartosz Golaszewski @ 2026-05-26 13:10 UTC (permalink / raw)
To: Vinod Koul, Jonathan Corbet, Thara Gopinath, Herbert Xu,
David S. Miller, Udit Tiwari, Md Sadre Alam, Dmitry Baryshkov,
Manivannan Sadhasivam, Stephan Gerhold, Bjorn Andersson,
Peter Ujfalusi, Michal Simek, Frank Li, Andy Gross,
Neil Armstrong
Cc: dmaengine, linux-doc, linux-kernel, linux-arm-msm, linux-crypto,
linux-arm-kernel, brgl, Bartosz Golaszewski, Bartosz Golaszewski,
Konrad Dybcio
In-Reply-To: <20260526-qcom-qce-cmd-descr-v19-0-08472fdcbf4a@oss.qualcomm.com>
From: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Switch to devm_kmalloc() and devm_dma_alloc_chan() in
devm_qce_dma_request(). This allows us to drop two labels and shrink the
function.
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
---
drivers/crypto/qce/dma.c | 34 +++++++++++-----------------------
1 file changed, 11 insertions(+), 23 deletions(-)
diff --git a/drivers/crypto/qce/dma.c b/drivers/crypto/qce/dma.c
index d60efb5c26d88f8b0259b1dccc8724d0f75571c6..c2602d35baa6ad3ca5de734de7ff6160ff29567c 100644
--- a/drivers/crypto/qce/dma.c
+++ b/drivers/crypto/qce/dma.c
@@ -12,7 +12,7 @@
#define QCE_IGNORE_BUF_SZ (2 * QCE_BAM_BURST_SIZE)
-static void qce_dma_release(void *data)
+static void qce_dma_terminate(void *data)
{
struct qce_dma_data *dma = data;
@@ -27,34 +27,22 @@ int devm_qce_dma_request(struct qce_device *qce)
{
struct qce_dma_data *dma = &qce->dma;
struct device *dev = qce->dev;
- int ret;
- dma->txchan = dma_request_chan(dev, "tx");
+ dma->result_buf = devm_kmalloc(dev, QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ, GFP_KERNEL);
+ if (!dma->result_buf)
+ return -ENOMEM;
+
+ dma->txchan = devm_dma_request_chan(dev, "tx");
if (IS_ERR(dma->txchan))
return dev_err_probe(dev, PTR_ERR(dma->txchan),
"Failed to get TX DMA channel\n");
- dma->rxchan = dma_request_chan(dev, "rx");
- if (IS_ERR(dma->rxchan)) {
- ret = dev_err_probe(dev, PTR_ERR(dma->rxchan),
- "Failed to get RX DMA channel\n");
- goto error_rx;
- }
-
- dma->result_buf = kmalloc(QCE_RESULT_BUF_SZ + QCE_IGNORE_BUF_SZ,
- GFP_KERNEL);
- if (!dma->result_buf) {
- ret = -ENOMEM;
- goto error_nomem;
- }
-
- return devm_add_action_or_reset(dev, qce_dma_release, dma);
+ dma->rxchan = devm_dma_request_chan(dev, "rx");
+ if (IS_ERR(dma->rxchan))
+ return dev_err_probe(dev, PTR_ERR(dma->rxchan),
+ "Failed to get RX DMA channel\n");
-error_nomem:
- dma_release_channel(dma->rxchan);
-error_rx:
- dma_release_channel(dma->txchan);
- return ret;
+ return devm_add_action_or_reset(dev, qce_dma_terminate, dma);
}
struct scatterlist *
--
2.47.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox