* [PATCH V2 00/11] soc: ti: keystone/k3 navigator queue/dma/ringacc cleanups
From: Nishanth Menon @ 2026-05-12 17:06 UTC (permalink / raw)
To: Justin Stitt, Bill Wendling, Nick Desaulniers, Nathan Chancellor,
Santosh Shilimkar
Cc: afd, Nishanth Menon, llvm, linux-arm-kernel, linux-kernel
Fix W=2 (clang/gcc), sparse, smatch and coccinelle warnings.
No functional changes.
Tested: NFS boot (via nav subsystem) on k2l-evm, k2hk-evm and k2g-evm
based on next-20260507:
https://gist.github.com/nmenon/cff02a5f2a72fde5fcb49664fcc834d2
Changes since V1:
- update for review comments.
- Picked up Randy's and Andrew's tags in appropriate patches.
V1: https://lore.kernel.org/all/20260508153211.3688277-1-nm@ti.com/
Nishanth Menon (11):
soc: ti: knav_qmss: Remove remaining redundant ENOMEM printks
soc: ti: knav_qmss: Rename global kdev to knav_qdev to fix -Wshadow
soc: ti: knav_qmss: Inline lockdep condition in for_each_handle_rcu
soc: ti: knav_qmss: Fix kernel-doc Return: tags
soc: ti: knav_qmss: Use %pe to print PTR_ERR()
soc: ti: knav_qmss: Fix __iomem annotations and __be32 type
soc: ti: knav_qmss_acc: Fix kernel-doc Return: tag
soc: ti: knav_dma: Remove unused DMA_PRIO_MASK macro
soc: ti: knav_dma: Remove dead check on unsigned args.args[0]
soc: ti: knav_dma: Use IOMEM_ERR_PTR() in pktdma_get_regs()
soc: ti: k3-ringacc: Use str_enabled_disabled() helper
drivers/soc/ti/k3-ringacc.c | 3 +-
drivers/soc/ti/knav_dma.c | 8 +-
drivers/soc/ti/knav_qmss.h | 2 +-
drivers/soc/ti/knav_qmss_acc.c | 2 +-
drivers/soc/ti/knav_qmss_queue.c | 148 +++++++++++++++----------------
5 files changed, 75 insertions(+), 88 deletions(-)
--
2.47.0
^ permalink raw reply
* Re: [PATCH v2 05/16] iio: adc: mediatek: add mt6323 PMIC AUXADC driver
From: Jonathan Cameron @ 2026-05-12 17:04 UTC (permalink / raw)
To: Roman Vivchar
Cc: Andy Shevchenko, David Lechner, Nuno Sá, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <gWxamwTKyUeOF4QCsiIsrnh7DSWzIKFaY0h83qKq_0vg786xv1uFYhypix7BVO_ruG_vw3DrIsRhIKv5NAzl8hK72rjzPAjwAGU-rhkMgeA=@protonmail.com>
On Tue, 12 May 2026 14:34:55 +0000
Roman Vivchar <rva333@protonmail.com> wrote:
> On Tuesday, May 12th, 2026 at 4:29 PM, Jonathan Cameron <jic23@kernel.org> wrote:
>
> > On Tue, 12 May 2026 08:18:19 +0300
> > Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
>
> ...
>
> > > +#define VOLTAGE_FULL_RANGE 1800
> > Probably better to have this inline - however if you do keep it
> > prefix t he define VOLTAGE_FULL_RANGE sounds too generic!
> >
> > > +#define AUXADC_PRECISE 32768
> > I'd put that inline. Little benefit it in having it up here...
>
> There was a mention about magic values in the v1 for the thermal patch [1].
> Andy, would it be better to use an inline style or a #define here?
> If the former, I'll rename the first constant to something like
> AUXADC_VOLTAGE_FULL_RANGE.
FWIW that isn't a magic value - it's 2**resolution and the one is a voltage
in mV. Those aren't normally the ones people care about defines for - those
apply when they are weird and wonderful things not related directly to physical
quantities.
Jonathan
>
> [1]: https://lore.kernel.org/linux-mediatek/afmnUG8dG0N0HpV6@ashevche-desk.local/
>
> Best regards,
> Roman
^ permalink raw reply
* Re: [PATCH RFC v2 1/4] dt-bindings: clk: zte: Add zx297520v3 clock and reset bindings.
From: Conor Dooley @ 2026-05-12 17:02 UTC (permalink / raw)
To: Stefan Dösinger
Cc: Michael Turquette, Stephen Boyd, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, linux-clk, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <DD71E384-1777-47B8-93C8-D6EFDA4BA74C@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2106 bytes --]
On Tue, May 12, 2026 at 12:33:42AM +0300, Stefan Dösinger wrote:
> Hi Conor,
>
> Thanks for your reply!
>
> > Am 11.05.2026 um 19:07 schrieb Conor Dooley <conor@kernel.org>:
> >
> > How come the "matrixclk" has no constraints on clock properties?
>
> Because I am not sure what the correct/preferred way to express the interface between top and matrix is - see the first question raised in my cover letter.
>
> In short, matrix potentially consumes all clocks available on the top controller. There is no obvious interface between them, like there is between matrix and LSP. So I see two ways to handle this in the bindings:
>
> 1) List the top clk inputs, top clk PLL outputs and PLL fractionals as matrix input
> 2) Be quiet about it
Unless you want to model top + matrix as a single node with two register
regions, then list it all. Hiding the relationships is ill-advised IMO.
>
> It'd be about 20 clocks or so that I know are consumed. The bigger issue than the number of clocks is that my knowledge of the board is from reverse engineering, not proper datasheets, so I might find out that a clock is missing or wrong.
>
> > Although, these two devices seem too different to be in the same
> > dt-binding. Do they have anyhting in common other than the SoC they are
> > part of?
>
> No, they don't have anything in common, other than that their concerns are poorly separated in hardware.
>
> I take it from your question that the preferred way is to have separate bindings for them in this case - I guess separate headers as well as separate yaml files. Is this correct?
Separate headers if you like, separate bindings since the hardware and
binding are completely different between devices.
> The third clock controller - LSP - is nicely separated from the other two. I would not be surprised to see this subsystem of the board show up on a different ZTE board. If top and matrix should have different bindings, LSP certainly should as well.
The "two" I was referring to were the two with constraints, so top and
lsp, so that should answer that!
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] arm64: dts: allwinner: Cubie A5E: enable SPI flash
From: Jernej Škrabec @ 2026-05-12 16:00 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Samuel Holland, Andre Przywara
Cc: devicetree, linux-arm-kernel, linux-sunxi
In-Reply-To: <20260511221741.25888-1-andre.przywara@arm.com>
Dne torek, 12. maj 2026 ob 00:17:41 Srednjeevropski poletni čas je Andre Przywara napisal(a):
> The Cubie A5E board comes with 16MiB of SPI NOR flash.
>
> Enable the SPI0 DT node and describe the configuration.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Best regards,
Jernej
^ permalink raw reply
* Re: [PATCH v2 05/16] iio: adc: mediatek: add mt6323 PMIC AUXADC driver
From: Andy Shevchenko @ 2026-05-12 16:56 UTC (permalink / raw)
To: Roman Vivchar
Cc: Jonathan Cameron, Andy Shevchenko, David Lechner, Nuno Sá,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Sen Chu, Sean Wang, Macpaul Lin,
Lee Jones, Srinivas Kandagatla, Rafael J. Wysocki, Daniel Lezcano,
Zhang Rui, Lukasz Luba, linux-iio, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek, linux-pm, Ben Grisdale
In-Reply-To: <gWxamwTKyUeOF4QCsiIsrnh7DSWzIKFaY0h83qKq_0vg786xv1uFYhypix7BVO_ruG_vw3DrIsRhIKv5NAzl8hK72rjzPAjwAGU-rhkMgeA=@protonmail.com>
On Tue, May 12, 2026 at 02:34:55PM +0000, Roman Vivchar wrote:
> On Tuesday, May 12th, 2026 at 4:29 PM, Jonathan Cameron <jic23@kernel.org> wrote:
> > On Tue, 12 May 2026 08:18:19 +0300
> > Roman Vivchar via B4 Relay <devnull+rva333.protonmail.com@kernel.org> wrote:
...
> > > +#define VOLTAGE_FULL_RANGE 1800
> > Probably better to have this inline - however if you do keep it
> > prefix t he define VOLTAGE_FULL_RANGE sounds too generic!
> >
> > > +#define AUXADC_PRECISE 32768
> > I'd put that inline. Little benefit it in having it up here...
>
> There was a mention about magic values in the v1 for the thermal patch [1].
> Andy, would it be better to use an inline style or a #define here?
> If the former, I'll rename the first constant to something like
> AUXADC_VOLTAGE_FULL_RANGE.
If you use it inline, add a comment to explain the magic.
It will be a good compromise.
> [1]: https://lore.kernel.org/linux-mediatek/afmnUG8dG0N0HpV6@ashevche-desk.local/
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH] ARM: OMAP2+: Make OMAP4 finish_suspend callback CFI-safe
From: Mithil Bavishi @ 2026-05-12 16:53 UTC (permalink / raw)
To: nathan
Cc: aaro.koskinen, andreas, bavishimithil, kees, khilman,
linux-arm-kernel, linux-kernel, linux-omap, linux, llvm, rogerq,
samitolvanen, tony
In-Reply-To: <20260512135757.GB570003@ax162>
> I don't think we have any formal documentation for SYM_TYPED_FUNC_START
> (it should probably be documented via kernel-doc?) but you can read the
> commit message of the change that added it for more information:
>
> e84e008e7b02 ("cfi: Add type helper macros")
Thanks, I had a look at it and other similar commits like
c50d328 ("arm64: Add types to indirect called assembly functions")
I was not aware of SYM_TYPED_FUNC_START before hence the logical approach
was just to wrap the function. But now with this I'll send a v2 with the
ENTRY and ENDPROC changed to SYM_TYPED_FUNC_START and SYM_FUNC_END.
Best,
Mithil
^ permalink raw reply
* Re: [PATCH 1/1] dt-bindings: display: imx: add deprecated property 'port' and 'display-timings'
From: Conor Dooley @ 2026-05-12 16:47 UTC (permalink / raw)
To: Frank Li
Cc: Philipp Zabel, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam,
open list:DRM DRIVERS FOR FREESCALE IMX 5/6,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
open list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
open list
In-Reply-To: <20260511220924.1905571-1-Frank.Li@nxp.com>
[-- Attachment #1: Type: text/plain, Size: 1678 bytes --]
On Mon, May 11, 2026 at 06:09:24PM -0400, Frank Li wrote:
> Add deprecated property 'port' and 'display-timings' for i.MX5 SoCs (over
> 15 years) to fix below CHECK_DTBS warnings:
> arm/boot/dts/nxp/imx/imx51-apf51dev.dtb: disp1 (fsl,imx-parallel-display): 'display-timings', 'port' do not match any of the regexes: '^pinctrl-[0-9]+$'
> from schema $id: http://devicetree.org/schemas/display/imx/fsl,imx-parallel-display.yaml
Instead of documenting the deprecated properties, could this
device/devicetree be converted to non-deprecated properties?
>
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> .../display/imx/fsl,imx-parallel-display.yaml | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-parallel-display.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx-parallel-display.yaml
> index bbcfe7e2958b7..b0c5869771fae 100644
> --- a/Documentation/devicetree/bindings/display/imx/fsl,imx-parallel-display.yaml
> +++ b/Documentation/devicetree/bindings/display/imx/fsl,imx-parallel-display.yaml
> @@ -42,6 +42,17 @@ properties:
> unevaluatedProperties: false
> description: output port connected to a panel
>
> + port:
> + $ref: /schemas/graph.yaml#/properties/port
> + unevaluatedProperties: false
> + deprecated: true
> + description: input port connected to the IPU display interface, see port@0
> +
> + display-timings:
> + $ref: /schemas/display/panel/display-timings.yaml#
> + unevaluatedProperties: false
> + deprecated: true
> +
> required:
> - compatible
>
> --
> 2.43.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH v5 9/9] crypto: atmel: Use dmaengine_prep_config_single() API
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Using new API dmaengine_prep_config_single() to simple code.
No functional change.
Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
drivers/crypto/atmel-aes.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index b393689400b4c17294cba73fcd16567fdd6687f4..d890b5a277b9c1394d2c7912bd663ff86321099f 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -795,7 +795,6 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
struct dma_slave_config config;
dma_async_tx_callback callback;
struct atmel_aes_dma *dma;
- int err;
memset(&config, 0, sizeof(config));
config.src_addr_width = addr_width;
@@ -820,12 +819,9 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
return -EINVAL;
}
- err = dmaengine_slave_config(dma->chan, &config);
- if (err)
- return err;
-
- desc = dmaengine_prep_slave_sg(dma->chan, dma->sg, dma->sg_len, dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ desc = dmaengine_prep_config_sg(dma->chan, dma->sg, dma->sg_len, dir,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+ &config);
if (!desc)
return -ENOMEM;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Use dmaengine_prep_config_single() to simplify
pci_epf_mhi_edma_read[_sync]() and pci_epf_mhi_edma_write[_sync]().
No functional change.
Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Keep mutex lock because sync with other function.
---
drivers/pci/endpoint/functions/pci-epf-mhi.c | 52 +++++++++-------------------
1 file changed, 16 insertions(+), 36 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
index 7f5326925ed54abf4ae75c465dfe0a9bab37ce40..c3e3b58fb86cd75e175b69ca45530610c500b99e 100644
--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
@@ -328,12 +328,6 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
config.direction = DMA_DEV_TO_MEM;
config.src_addr = buf_info->host_addr;
- ret = dmaengine_slave_config(chan, &config);
- if (ret) {
- dev_err(dev, "Failed to configure DMA channel\n");
- goto err_unlock;
- }
-
dst_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
DMA_FROM_DEVICE);
ret = dma_mapping_error(dma_dev, dst_addr);
@@ -342,9 +336,10 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
goto err_unlock;
}
- desc = dmaengine_prep_slave_single(chan, dst_addr, buf_info->size,
- DMA_DEV_TO_MEM,
- DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+ desc = dmaengine_prep_config_single(chan, dst_addr, buf_info->size,
+ DMA_DEV_TO_MEM,
+ DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+ &config);
if (!desc) {
dev_err(dev, "Failed to prepare DMA\n");
ret = -EIO;
@@ -401,12 +396,6 @@ static int pci_epf_mhi_edma_write(struct mhi_ep_cntrl *mhi_cntrl,
config.direction = DMA_MEM_TO_DEV;
config.dst_addr = buf_info->host_addr;
- ret = dmaengine_slave_config(chan, &config);
- if (ret) {
- dev_err(dev, "Failed to configure DMA channel\n");
- goto err_unlock;
- }
-
src_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
DMA_TO_DEVICE);
ret = dma_mapping_error(dma_dev, src_addr);
@@ -415,9 +404,10 @@ static int pci_epf_mhi_edma_write(struct mhi_ep_cntrl *mhi_cntrl,
goto err_unlock;
}
- desc = dmaengine_prep_slave_single(chan, src_addr, buf_info->size,
- DMA_MEM_TO_DEV,
- DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+ desc = dmaengine_prep_config_single(chan, src_addr, buf_info->size,
+ DMA_MEM_TO_DEV,
+ DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+ &config);
if (!desc) {
dev_err(dev, "Failed to prepare DMA\n");
ret = -EIO;
@@ -506,12 +496,6 @@ static int pci_epf_mhi_edma_read_async(struct mhi_ep_cntrl *mhi_cntrl,
config.direction = DMA_DEV_TO_MEM;
config.src_addr = buf_info->host_addr;
- ret = dmaengine_slave_config(chan, &config);
- if (ret) {
- dev_err(dev, "Failed to configure DMA channel\n");
- goto err_unlock;
- }
-
dst_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
DMA_FROM_DEVICE);
ret = dma_mapping_error(dma_dev, dst_addr);
@@ -520,9 +504,10 @@ static int pci_epf_mhi_edma_read_async(struct mhi_ep_cntrl *mhi_cntrl,
goto err_unlock;
}
- desc = dmaengine_prep_slave_single(chan, dst_addr, buf_info->size,
- DMA_DEV_TO_MEM,
- DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+ desc = dmaengine_prep_config_single(chan, dst_addr, buf_info->size,
+ DMA_DEV_TO_MEM,
+ DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+ &config);
if (!desc) {
dev_err(dev, "Failed to prepare DMA\n");
ret = -EIO;
@@ -585,12 +570,6 @@ static int pci_epf_mhi_edma_write_async(struct mhi_ep_cntrl *mhi_cntrl,
config.direction = DMA_MEM_TO_DEV;
config.dst_addr = buf_info->host_addr;
- ret = dmaengine_slave_config(chan, &config);
- if (ret) {
- dev_err(dev, "Failed to configure DMA channel\n");
- goto err_unlock;
- }
-
src_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
DMA_TO_DEVICE);
ret = dma_mapping_error(dma_dev, src_addr);
@@ -599,9 +578,10 @@ static int pci_epf_mhi_edma_write_async(struct mhi_ep_cntrl *mhi_cntrl,
goto err_unlock;
}
- desc = dmaengine_prep_slave_single(chan, src_addr, buf_info->size,
- DMA_MEM_TO_DEV,
- DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+ desc = dmaengine_prep_config_single(chan, src_addr, buf_info->size,
+ DMA_MEM_TO_DEV,
+ DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+ &config);
if (!desc) {
dev_err(dev, "Failed to prepare DMA\n");
ret = -EIO;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Use the new dmaengine_prep_config_single_safe() API to combine the
configuration and descriptor preparation into a single call.
Since dmaengine_prep_config_single_safe() performs the configuration and
preparation atomically and the mutex can be removed.
Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
drivers/nvme/target/pci-epf.c | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 2afe8f4d0e46104a1b3c98db3905cf33e8c9e011..04d8f48d6950349ca97d2dbeae4e38e4714ad0d4 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -388,22 +388,15 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
return -EINVAL;
}
- mutex_lock(lock);
-
dma_dev = dmaengine_get_dma_device(chan);
dma_addr = dma_map_single(dma_dev, seg->buf, seg->length, dir);
ret = dma_mapping_error(dma_dev, dma_addr);
if (ret)
- goto unlock;
-
- ret = dmaengine_slave_config(chan, &sconf);
- if (ret) {
- dev_err(dev, "Failed to configure DMA channel\n");
- goto unmap;
- }
+ return ret;
- desc = dmaengine_prep_slave_single(chan, dma_addr, seg->length,
- sconf.direction, DMA_CTRL_ACK);
+ desc = dmaengine_prep_config_single_safe(chan, dma_addr, seg->length,
+ sconf.direction,
+ DMA_CTRL_ACK, &sconf);
if (!desc) {
dev_err(dev, "Failed to prepare DMA\n");
ret = -EIO;
@@ -426,9 +419,6 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
unmap:
dma_unmap_single(dma_dev, dma_addr, seg->length, dir);
-unlock:
- mutex_unlock(lock);
-
return ret;
}
--
2.43.0
^ permalink raw reply related
* [PATCH v5 6/9] nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
Damien Le Moal
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
dmaengine_terminate_sync() cancels all pending requests. Calling it for
every DMA transfer is unnecessary and counterproductive. This function is
generally intended for cleanup paths such as module removal, device close,
or unbind operations.
Remove the redundant calls for success path and keep it only at error path.
Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
This one also fix stress test failure after remove mutex and use new API
dmaengine_prep_slave_sg_config().
---
drivers/nvme/target/pci-epf.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 4e9db96ebfecd796244e5dc67c23e1abb1a14974..2afe8f4d0e46104a1b3c98db3905cf33e8c9e011 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -420,10 +420,9 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
if (dma_sync_wait(chan, cookie) != DMA_COMPLETE) {
dev_err(dev, "DMA transfer failed\n");
ret = -EIO;
+ dmaengine_terminate_sync(chan);
}
- dmaengine_terminate_sync(chan);
-
unmap:
dma_unmap_single(dma_dev, dma_addr, seg->length, dir);
--
2.43.0
^ permalink raw reply related
* [PATCH v5 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Pass dma_slave_config to dw_edma_device_transfer() to support atomic
configuration and descriptor preparation when a non-NULL config is
provided to device_prep_config_sg().
Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- rewrite dw_edma_device_slave_config() according to Damien's suggestion.
---
drivers/dma/dw-edma/dw-edma-core.c | 27 +++++++++++++++++++++------
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index f7f58b0010e26b529ffb7382d5b166a703587c71..ec6f6b1e482568a27ebe90852d5679672b24a1e9 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -267,6 +267,20 @@ static int dw_edma_device_config(struct dma_chan *dchan,
return 0;
}
+static struct dma_slave_config *
+dw_edma_device_get_config(struct dma_chan *dchan,
+ struct dma_slave_config *config)
+{
+ struct dw_edma_chan *chan;
+
+ if (config)
+ return config;
+
+ chan = dchan2dw_edma_chan(dchan);
+
+ return &chan->config;
+}
+
static int dw_edma_device_pause(struct dma_chan *dchan)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
@@ -385,7 +399,8 @@ dw_edma_device_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
}
static struct dma_async_tx_descriptor *
-dw_edma_device_transfer(struct dw_edma_transfer *xfer)
+dw_edma_device_transfer(struct dw_edma_transfer *xfer,
+ struct dma_slave_config *config)
{
struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan);
enum dma_transfer_direction dir = xfer->direction;
@@ -472,8 +487,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
src_addr = xfer->xfer.il->src_start;
dst_addr = xfer->xfer.il->dst_start;
} else {
- src_addr = chan->config.src_addr;
- dst_addr = chan->config.dst_addr;
+ src_addr = config->src_addr;
+ dst_addr = config->dst_addr;
}
if (dir == DMA_DEV_TO_MEM)
@@ -595,7 +610,7 @@ dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
if (config)
dw_edma_device_config(dchan, config);
- return dw_edma_device_transfer(&xfer);
+ return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, config));
}
static struct dma_async_tx_descriptor *
@@ -614,7 +629,7 @@ dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t paddr,
xfer.flags = flags;
xfer.type = EDMA_XFER_CYCLIC;
- return dw_edma_device_transfer(&xfer);
+ return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL));
}
static struct dma_async_tx_descriptor *
@@ -630,7 +645,7 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan,
xfer.flags = flags;
xfer.type = EDMA_XFER_INTERLEAVED;
- return dw_edma_device_transfer(&xfer);
+ return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL));
}
static void dw_hdma_set_callback_result(struct virt_dma_desc *vd,
--
2.43.0
^ permalink raw reply related
* [PATCH v5 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
Damien Le Moal
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Use the new .device_prep_config_sg() callback to combine configuration and
descriptor preparation.
No functional changes.
Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v4
- drop context in callback.
change in v3
- add Damien Le Moal review tag
---
drivers/dma/dw-edma/dw-edma-core.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index c2feb3adc79fa94b016913443305b9fae9deef12..f7f58b0010e26b529ffb7382d5b166a703587c71 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -577,10 +577,11 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
}
static struct dma_async_tx_descriptor *
-dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
- unsigned int len,
- enum dma_transfer_direction direction,
- unsigned long flags, void *context)
+dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+ unsigned int len,
+ enum dma_transfer_direction direction,
+ unsigned long flags,
+ struct dma_slave_config *config)
{
struct dw_edma_transfer xfer;
@@ -591,6 +592,9 @@ dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
xfer.flags = flags;
xfer.type = EDMA_XFER_SCATTER_GATHER;
+ if (config)
+ dw_edma_device_config(dchan, config);
+
return dw_edma_device_transfer(&xfer);
}
@@ -970,7 +974,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
dma->device_terminate_all = dw_edma_device_terminate_all;
dma->device_issue_pending = dw_edma_device_issue_pending;
dma->device_tx_status = dw_edma_device_tx_status;
- dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg;
+ dma->device_prep_config_sg = dw_edma_device_prep_config_sg;
dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic;
dma->device_prep_interleaved_dma = dw_edma_device_prep_interleaved_dma;
--
2.43.0
^ permalink raw reply related
* [PATCH v5 3/9] PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
Damien Le Moal
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Use dmaenigne_prep_config_single() to simplify code.
No functional change.
Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- add Damien Le Moal review tag
---
drivers/pci/endpoint/functions/pci-epf-test.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 591d301fa89d89addf5df16e775e80460b689589..0f5cf2d7951088af3801ea1cc240b2ea8627eed5 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -182,12 +182,8 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
else
sconf.src_addr = dma_remote;
- if (dmaengine_slave_config(chan, &sconf)) {
- dev_err(dev, "DMA slave config fail\n");
- return -EIO;
- }
- tx = dmaengine_prep_slave_single(chan, dma_local, len, dir,
- flags);
+ tx = dmaengine_prep_config_single(chan, dma_local, len,
+ dir, flags, &sconf);
} else {
tx = dmaengine_prep_dma_memcpy(chan, dma_dst, dma_src, len,
flags);
--
2.43.0
^ permalink raw reply related
* [PATCH v5 2/9] dmaengine: Add safe API to combine configuration and preparation
From: Frank Li @ 2026-05-12 16:42 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Introduce dmaengine_prep_config_single_safe() and
dmaengine_prep_config_sg_safe() to provide a reentrant-safe way to
combine slave configuration and transfer preparation.
Drivers may implement the new device_prep_config_sg() callback to perform
both steps atomically. If the callback is not provided, the helpers fall
back to calling dmaengine_slave_config() followed by
dmaengine_prep_slave_sg() under per-channel mutex protection.
Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
chagne in v5
- remove reduntant lock commments.
- use kernel doc to descritp API
chagne in v4
- use spinlock() to protect config() and prep()
change in v3
- new patch
---
drivers/dma/dmaengine.c | 2 ++
include/linux/dmaengine.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 87 insertions(+)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 405bd2fbb4a3b94fd0bf44526f656f6a19feaad0..ba29e60160c1a0148793bb299849bccfebb6d32b 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1099,6 +1099,8 @@ static int __dma_async_device_channel_register(struct dma_device *device,
chan->dev->device.parent = device->dev;
chan->dev->chan = chan;
chan->dev->dev_id = device->dev_id;
+ spin_lock_init(&chan->lock);
+
if (!name)
dev_set_name(&chan->dev->device, "dma%dchan%d", device->dev_id, chan->chan_id);
else
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index defa377d2ef54d94e6337cdfa7826a091295535e..83e8547de89bf56424f048c316bdc8d798791e25 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -322,6 +322,8 @@ struct dma_router {
* @slave: ptr to the device using this channel
* @cookie: last cookie value returned to client
* @completed_cookie: last completed cookie for this channel
+ * @lock: protect between config and prepare transfer when driver have not
+ * implemented callback device_prep_config_sg().
* @chan_id: channel ID for sysfs
* @dev: class device for sysfs
* @name: backlink name for sysfs
@@ -341,6 +343,12 @@ struct dma_chan {
dma_cookie_t cookie;
dma_cookie_t completed_cookie;
+ /*
+ * protect between config and prepare transfer because *_prep() may be
+ * called from complete callback, which is in GFP_NOSLEEP context.
+ */
+ spinlock_t lock;
+
/* sysfs */
int chan_id;
struct dma_chan_dev *dev;
@@ -1068,6 +1076,83 @@ dmaengine_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
return dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, NULL);
}
+/**
+ * dmaengine_prep_config_sg_safe - prepare a scatter-gather DMA transfer
+ * with atomic slave configuration update
+ * @chan: DMA channel
+ * @sgl: scatterlist for the transfer
+ * @sg_len: number of entries in @sgl
+ * @dir: DMA transfer direction
+ * @flags: transfer preparation flags
+ * @config: DMA slave configuration for this transfer
+ *
+ * Prepare a DMA scatter-gather transfer together with a corresponding slave
+ * configuration update in a re-entrant and race-safe manner.
+ *
+ * DMA engine drivers may implement the optional
+ * device_prep_config_sg() callback to perform both the slave configuration
+ * and descriptor preparation atomically. In this case, the operation is
+ * fully handled by the DMA engine driver.
+ *
+ * If the DMA engine driver does not implement device_prep_config_sg(), falls
+ * back to calling dmaengine_slave_config() followed by dmaengine_prep_slave_sg().
+ * The fallback path is protected by a per-channel spinlock to ensure that
+ * concurrent callers cannot interleave configuration and descriptor preparation
+ * on the same DMA channel.
+ *
+ * Return: Pointer to a prepared DMA async transaction descriptor on success,
+ * or %NULL if the transfer could not be prepared.
+ */
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_sg_safe(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len,
+ enum dma_transfer_direction dir,
+ unsigned long flags,
+ struct dma_slave_config *config)
+{
+ struct dma_async_tx_descriptor *tx;
+
+ if (!chan || !chan->device)
+ return NULL;
+
+ if (!chan->device->device_prep_config_sg)
+ spin_lock(&chan->lock);
+
+ tx = dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, config);
+
+ if (!chan->device->device_prep_config_sg)
+ spin_unlock(&chan->lock);
+
+ return tx;
+}
+
+/**
+ * dmaengine_prep_config_single_safe - prepare a single-buffer DMA transfer
+ * with atomic slave configuration update
+ * @chan: DMA channel
+ * @buf: DMA buffer address
+ * @len: length of the transfer in bytes
+ * @dir: DMA transfer direction
+ * @flags: transfer preparation flags
+ * @config: DMA slave configuration for this transfer
+ *
+ * Detail see dmaengine_prep_config_sg_safe().
+ */
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_single_safe(struct dma_chan *chan, dma_addr_t buf,
+ size_t len, enum dma_transfer_direction dir,
+ unsigned long flags,
+ struct dma_slave_config *config)
+{
+ struct scatterlist sg;
+
+ sg_init_table(&sg, 1);
+ sg_dma_address(&sg) = buf;
+ sg_dma_len(&sg) = len;
+
+ return dmaengine_prep_config_sg_safe(chan, &sg, 1, dir, flags, config);
+}
+
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct rio_dma_ext;
static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(
--
2.43.0
^ permalink raw reply related
* [PATCH v5 1/9] dmaengine: Add API to combine configuration and preparation (sg and single)
From: Frank Li @ 2026-05-12 16:41 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li
In-Reply-To: <20260512-dma_prep_config-v5-0-26865bf7d935@nxp.com>
Previously, configuration and preparation required two separate calls. This
works well when configuration is done only once during initialization.
However, in cases where the burst length or source/destination address must
be adjusted for each transfer, calling two functions is verbose and
requires additional locking to ensure both steps complete atomically.
Add a new API dmaengine_prep_config_single() and dmaengine_prep_config_sg()
and callback device_prep_config_sg() that combines configuration and
preparation into a single operation. If the configuration argument is
passed as NULL, fall back to the existing implementation.
Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v4
- drop context in device_prep_config_sg()
change in v3
- remove Deprecated for callback device_prep_slave_sg().
- Move condition check before sg init.
- split function at return type.
- move safe version to next patch
change in v2
- add () for function
- use short name device_prep_sg(), remove "slave" and "config". the 'slave'
is reduntant. after remove slave, the function name is difference existed
one, so remove _config suffix.
---
Documentation/driver-api/dmaengine/client.rst | 9 ++++
include/linux/dmaengine.h | 63 +++++++++++++++++++++++----
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/Documentation/driver-api/dmaengine/client.rst b/Documentation/driver-api/dmaengine/client.rst
index d491e385d61a98b8a804cd823caf254a2dc62cf4..5ee5d4a3596dd986b02f1bce3078ca6c4c1fb45a 100644
--- a/Documentation/driver-api/dmaengine/client.rst
+++ b/Documentation/driver-api/dmaengine/client.rst
@@ -80,6 +80,10 @@ The details of these operations are:
- slave_sg: DMA a list of scatter gather buffers from/to a peripheral
+ - config_sg: Similar with slave_sg, just pass down dma_slave_config
+ struct to avoid calling dmaengine_slave_config() every time adjusting the
+ burst length or the FIFO address is needed.
+
- peripheral_dma_vec: DMA an array of scatter gather buffers from/to a
peripheral. Similar to slave_sg, but uses an array of dma_vec
structures instead of a scatterlist.
@@ -106,6 +110,11 @@ The details of these operations are:
unsigned int sg_len, enum dma_data_direction direction,
unsigned long flags);
+ struct dma_async_tx_descriptor *dmaengine_prep_config_sg(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction dir,
+ unsigned long flags, struct dma_slave_config *config);
+
struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
struct dma_chan *chan, const struct dma_vec *vecs,
size_t nents, enum dma_data_direction direction,
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index b3d251c9734e95e1b75cf6763d4d2c3a1c6a9910..defa377d2ef54d94e6337cdfa7826a091295535e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -835,6 +835,7 @@ struct dma_filter {
* where the address and size of each segment is located in one entry of
* the dma_vec array.
* @device_prep_slave_sg: prepares a slave dma operation
+ * @device_prep_config_sg: prepares a slave DMA operation with dma_slave_config
* @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio.
* The function takes a buffer of size buf_len. The callback function will
* be called after period_len bytes have been transferred.
@@ -934,6 +935,10 @@ struct dma_device {
struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction direction,
unsigned long flags, void *context);
+ struct dma_async_tx_descriptor *(*device_prep_config_sg)(
+ struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction direction,
+ unsigned long flags, struct dma_slave_config *config);
struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
size_t period_len, enum dma_transfer_direction direction,
@@ -974,22 +979,44 @@ static inline bool is_slave_direction(enum dma_transfer_direction direction)
(direction == DMA_DEV_TO_DEV);
}
-static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
- struct dma_chan *chan, dma_addr_t buf, size_t len,
- enum dma_transfer_direction dir, unsigned long flags)
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_single(struct dma_chan *chan, dma_addr_t buf, size_t len,
+ enum dma_transfer_direction dir,
+ unsigned long flags,
+ struct dma_slave_config *config)
{
struct scatterlist sg;
+
+ if (!chan || !chan->device)
+ return NULL;
+
sg_init_table(&sg, 1);
sg_dma_address(&sg) = buf;
sg_dma_len(&sg) = len;
- if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
+ if (chan->device->device_prep_config_sg)
+ return chan->device->device_prep_config_sg(chan, &sg, 1, dir,
+ flags, config);
+
+ if (config)
+ if (dmaengine_slave_config(chan, config))
+ return NULL;
+
+ if (!chan->device->device_prep_slave_sg)
return NULL;
return chan->device->device_prep_slave_sg(chan, &sg, 1,
dir, flags, NULL);
}
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_slave_single(struct dma_chan *chan, dma_addr_t buf, size_t len,
+ enum dma_transfer_direction dir,
+ unsigned long flags)
+{
+ return dmaengine_prep_config_single(chan, buf, len, dir, flags, NULL);
+}
+
/**
* dmaengine_prep_peripheral_dma_vec() - Prepare a DMA scatter-gather descriptor
* @chan: The channel to be used for this descriptor
@@ -1010,17 +1037,37 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
dir, flags);
}
-static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
- struct dma_chan *chan, struct scatterlist *sgl, unsigned int sg_len,
- enum dma_transfer_direction dir, unsigned long flags)
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction dir,
+ unsigned long flags, struct dma_slave_config *config)
{
- if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
+ if (!chan || !chan->device)
+ return NULL;
+
+ if (chan->device->device_prep_config_sg)
+ return chan->device->device_prep_config_sg(chan, sgl, sg_len,
+ dir, flags, config);
+
+ if (config)
+ if (dmaengine_slave_config(chan, config))
+ return NULL;
+
+ if (!chan->device->device_prep_slave_sg)
return NULL;
return chan->device->device_prep_slave_sg(chan, sgl, sg_len,
dir, flags, NULL);
}
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+ unsigned int sg_len, enum dma_transfer_direction dir,
+ unsigned long flags)
+{
+ return dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, NULL);
+}
+
#ifdef CONFIG_RAPIDIO_DMA_ENGINE
struct rio_dma_ext;
static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(
--
2.43.0
^ permalink raw reply related
* [PATCH v5 0/9] dmaengine: Add new API to combine configuration and descriptor preparation
From: Frank Li @ 2026-05-12 16:41 UTC (permalink / raw)
To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
Niklas Cassel
Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
Damien Le Moal
Previously, configuration and preparation required two separate calls. This
works well when configuration is done only once during initialization.
However, in cases where the burst length or source/destination address must
be adjusted for each transfer, calling two functions is verbose.
if (dmaengine_slave_config(chan, &sconf)) {
dev_err(dev, "DMA slave config fail\n");
return -EIO;
}
tx = dmaengine_prep_slave_single(chan, dma_local, len, dir, flags);
After new API added
tx = dmaengine_prep_config_single(chan, dma_local, len, dir, flags, &sconf);
Additional, prevous two calls requires additional locking to ensure both
steps complete atomically.
mutex_lock()
dmaengine_slave_config()
dmaengine_prep_slave_single()
mutex_unlock()
after new API added, mutex lock can be moved. See patch
nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v5:
- collect Mani's reviewed-by tags
- use kernel doc for new APIs.
- Link to v4: https://lore.kernel.org/r/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com
Changes in v4:
- remove void* context in config_prep() callback
- use spin lock to protect config() and prep().
- Link to v3: https://lore.kernel.org/r/20260105-dma_prep_config-v3-0-a8480362fd42@nxp.com
Changes in v3:
- collect review tags
- create safe version in framework
- Link to v2: https://lore.kernel.org/r/20251218-dma_prep_config-v2-0-c07079836128@nxp.com
Changes in v2:
- Use name dmaengine_prep_config_single() and dmaengine_prep_config_sg()
- Add _safe version to avoid confuse, which needn't additional mutex.
- Update document/
- Update commit message. add () for function name. Use upcase for subject.
- Add more explain for remove lock.
- Link to v1: https://lore.kernel.org/r/20251208-dma_prep_config-v1-0-53490c5e1e2a@nxp.com
---
Frank Li (9):
dmaengine: Add API to combine configuration and preparation (sg and single)
dmaengine: Add safe API to combine configuration and preparation
PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code
dmaengine: dw-edma: Use new .device_prep_config_sg() callback
dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()
nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer
nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code
crypto: atmel: Use dmaengine_prep_config_single() API
Documentation/driver-api/dmaengine/client.rst | 9 ++
drivers/crypto/atmel-aes.c | 10 +-
drivers/dma/dmaengine.c | 2 +
drivers/dma/dw-edma/dw-edma-core.c | 41 +++++--
drivers/nvme/target/pci-epf.c | 21 +---
drivers/pci/endpoint/functions/pci-epf-mhi.c | 52 +++------
drivers/pci/endpoint/functions/pci-epf-test.c | 8 +-
include/linux/dmaengine.h | 148 ++++++++++++++++++++++++--
8 files changed, 207 insertions(+), 84 deletions(-)
---
base-commit: b9303e6bff706758c167af686b5315ad00233bf8
change-id: 20251204-dma_prep_config-654170d245a2
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
* Re: [RFC PATCH v3 3/7] hq-spinlock: add contention detection
From: Fedorov Nikita @ 2026-05-12 16:25 UTC (permalink / raw)
To: 1234567weewee457
Cc: fedorov.nikita, stepanov.anatoly, linux-kernel, linux-arm-kernel,
linux-arch, linux-mm, virtualization
In-Reply-To: <20260512144908.610907-1-1234567weewee457@gmail.com>
Hi!
You are right - a call was accidentally dropped while I was splitting the series.
Sorry about that. I rechecked the whole patch after fixing it.
This is a small fix.
Thanks,
Nikita
^ permalink raw reply
* [PATCH v3] locking/hqlock_core: restore missing call in contention detection logic
From: Fedorov Nikita @ 2026-05-12 16:25 UTC (permalink / raw)
To: 1234567weewee457
Cc: fedorov.nikita, stepanov.anatoly, linux-kernel, linux-arm-kernel,
linux-arch, linux-mm, virtualization
In-Reply-To: <20260512162503.1843025-1-fedorov.nikita@h-partners.com>
A call was accidentally dropped while splitting the hqspinlock patch series.
It did not break the system functionality,
but caused the lock to stay in QSPINLOCK mode.
Restore the missing call.
Sorry for missing this in the previous posting. I rechecked the whole path after fixing.
Signed-off-by: Nikita Fedorov <fedorov.nikita@h-partners.com>
---
kernel/locking/hqlock_core.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/kernel/locking/hqlock_core.h b/kernel/locking/hqlock_core.h
index 74f92ac3d8ad..226a0bb9a667 100644
--- a/kernel/locking/hqlock_core.h
+++ b/kernel/locking/hqlock_core.h
@@ -580,6 +580,8 @@ static inline void hqlock_clear_tail_handoff(struct qspinlock *lock, u32 val,
hqlock_handoff(lock, node, next, tail, handoff_info);
} else {
+ update_counters_qspinlock(qnode);
+
if ((val & _Q_TAIL_MASK) == tail) {
if (low_contention_try_clear_tail(lock, val, node))
return;
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] pmdomain: ti_sci: add wakeup constraint to parent devices of wakeup source
From: Kendall Willis @ 2026-05-12 16:17 UTC (permalink / raw)
To: Vitor Soares
Cc: Nishanth Menon, Tero Kristo, Santosh Shilimkar, Ulf Hansson,
Kevin Hilman, Dhruva Gole, linux-arm-kernel, linux-pm,
linux-kernel, stable, tomi.valkeinen, sebin.francis, devarsht,
vigneshr, vishalm, vitor.soares
In-Reply-To: <becb54adc0bea88578c8fe4c7c1b7b68bf5cc6d4.camel@gmail.com>
On 17:51-20260511, Vitor Soares wrote:
> Hi Kendall,
>
> On Wed, 2026-05-06 at 22:16 -0500, Kendall Willis wrote:
> > Set wakeup constraint for any device in a wakeup path. All parent devices
> > of a wakeup device should not be turned off during suspend. This ensures
> > the wakeup device is kept on while the system is suspended.
> >
>
> Thanks for the patch.
>
> I tested it on our Verdin AM62P. As expected, suspend now fails cleanly with "-
> 19" when an SDIO WiFi module is registered as a wakeup source, instead of
> crashing on resume:
>
> ti-sci 44043000.system-controller: PM: failed to suspend: error -19
>
> I did not test the IO daisy chain wakeup path, since that is out of scope for
> this patch.
>
> Best regards,
> Vitor Soares
>
Hi Vitor,
Thanks for testing the patch! Could you add your Tested-by tag?
Best,
Kendall
^ permalink raw reply
* Re: [PATCH 1/5] arm_mpam: Parse the rest of the ACPI table
From: Andre Przywara @ 2026-05-12 16:13 UTC (permalink / raw)
To: Ben Horgan, Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla,
Catalin Marinas, Will Deacon, Rafael J . Wysocki, Len Brown,
James Morse, Reinette Chatre, Fenghua Yu
Cc: Jonathan Cameron, linux-acpi, linux-arm-kernel, linux-kernel
In-Reply-To: <f12b8d73-7c8e-43e7-b9ce-d80a7c3f10c8@arm.com>
Hi Ben,
On 5/8/26 12:21, Ben Horgan wrote:
> Hi Andre,
>
> On 4/29/26 15:13, Andre Przywara wrote:
>> From: James Morse <james.morse@arm.com>
>>
>> The MPAM ACPI table lists the MPAM MSCs and indicates which resources
>> in the system they control. Not everything this table can describe is
>> supported by resctrl, e.g. memory-side-caches.
>>
>> Add the additional table parsing to avoid reporting these as 'unknown'
>> to the MPAM driver. This allows class+component hierarchys to be built.
>>
>> Until resctrl has support for any of these resources, users would be
>> in-kernel managers of a resource/PARTID or perf to query bandwidth
>> counters on a resource resctrl is unaware of.
>
> Does this patch give us anything needed for MPAM-Fb? It seems to just add
> parsing for things we don't support in the MPAM driver.
I think you are right, this just parses more resource types from the MSC
table, but is otherwise unrelated to MPAM-Fb.
I probably just cargo-culted this patch all the time ;-)
Will drop it now.
Cheers,
Andre.
>
> Thanks,
>
> Ben
>
>>
>> Signed-off-by: James Morse <james.morse@arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>> drivers/acpi/arm64/mpam.c | 91 +++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 88 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/acpi/arm64/mpam.c b/drivers/acpi/arm64/mpam.c
>> index 84963a20c3e7..99c2bdbb3314 100644
>> --- a/drivers/acpi/arm64/mpam.c
>> +++ b/drivers/acpi/arm64/mpam.c
>> @@ -95,17 +95,51 @@ static void acpi_mpam_parse_irqs(struct platform_device *pdev,
>> res[(*res_idx)++] = DEFINE_RES_IRQ_NAMED(irq, "error");
>> }
>>
>> -static int acpi_mpam_parse_resource(struct mpam_msc *msc,
>> +#define UUID_MPAM_INTERCONNECT_TABLE "fe2bd645-033b-49e6-9479-2e0b8b21d1cd"
>> +
>> +struct acpi_mpam_interconnect_descriptor_table {
>> + u8 type_uuid[16];
>> + u32 num_descriptors;
>> +};
>> +
>> +struct acpi_mpam_interconnect_descriptor {
>> + u32 source_id;
>> + u32 destination_id;
>> + u8 link_type;
>> + u8 reserved[3];
>> +};
>> +
>> +static int acpi_mpam_parse_resource(struct acpi_mpam_msc_node *tbl_msc,
>> + struct mpam_msc *msc,
>> struct acpi_mpam_resource_node *res)
>> {
>> + struct acpi_mpam_interconnect_descriptor_table *tbl_int_tbl;
>> + struct acpi_mpam_interconnect_descriptor *tbl_int;
>> + guid_t int_tbl_uuid, spec_uuid;
>> int level, nid;
>> u32 cache_id;
>> + off_t offset;
>>
>> + /*
>> + * Class IDs are somewhat arbitrary, but need to be co-ordinated.
>> + * 0-N are caches,
>> + * 64, 65: Interconnect, but ideally these would appear between the
>> + * classes the controls are adjacent to.
>> + * 128: SMMU,
>> + * 192-192+level: Memory Side Caches, nothing checks that N is a
>> + * small number.
>> + * 255: Memory Controllers
>> + *
>> + * ACPI devices would need a class id allocated based on the _HID.
>> + *
>> + * Classes that the mpam driver can't currently plumb into resctrl
>> + * are registered as UNKNOWN.
>> + */
>> switch (res->locator_type) {
>> case ACPI_MPAM_LOCATION_TYPE_PROCESSOR_CACHE:
>> cache_id = res->locator.cache_locator.cache_reference;
>> level = find_acpi_cache_level_from_id(cache_id);
>> - if (level <= 0) {
>> + if (level <= 0 || level >= 64) {
>> pr_err_once("Bad level (%d) for cache with id %u\n", level, cache_id);
>> return -EINVAL;
>> }
>> @@ -120,6 +154,57 @@ static int acpi_mpam_parse_resource(struct mpam_msc *msc,
>> }
>> return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_MEMORY,
>> MPAM_CLASS_ID_DEFAULT, nid);
>> + case ACPI_MPAM_LOCATION_TYPE_SMMU:
>> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_UNKNOWN,
>> + 128, res->locator.smmu_locator.smmu_interface);
>> + case ACPI_MPAM_LOCATION_TYPE_MEMORY_CACHE:
>> + cache_id = res->locator.mem_cache_locator.reference;
>> + level = res->locator.mem_cache_locator.level;
>> + if (192 + level >= 255) {
>> + pr_err_once("Bad level for memory side cache with reference %u\n",
>> + cache_id);
>> + return -EINVAL;
>> + }
>> +
>> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_CACHE,
>> + 192 + level, cache_id);
>> +
>> + case ACPI_MPAM_LOCATION_TYPE_INTERCONNECT:
>> + /* Find the descriptor table, and check it lands in the parent msc */
>> + offset = res->locator.interconnect_ifc_locator.inter_connect_desc_tbl_off;
>> + if (offset >= tbl_msc->length) {
>> + pr_err_once("Bad offset for interconnect descriptor on msc %u\n",
>> + tbl_msc->identifier);
>> + return -EINVAL;
>> + }
>> + tbl_int_tbl = ACPI_ADD_PTR(struct acpi_mpam_interconnect_descriptor_table,
>> + tbl_msc, offset);
>> + guid_parse(UUID_MPAM_INTERCONNECT_TABLE, &spec_uuid);
>> + import_guid(&int_tbl_uuid, tbl_int_tbl->type_uuid);
>> + if (guid_equal(&spec_uuid, &int_tbl_uuid)) {
>> + pr_err_once("Bad UUID for interconnect descriptor on msc %u\n",
>> + tbl_msc->identifier);
>> + return -EINVAL;
>> + }
>> +
>> + offset += sizeof(*tbl_int_tbl);
>> + offset += tbl_int_tbl->num_descriptors * sizeof(*tbl_int);
>> + if (offset >= tbl_msc->length) {
>> + pr_err_once("Bad num_descriptors for interconnect descriptor on msc %u\n",
>> + tbl_msc->identifier);
>> + return -EINVAL;
>> + }
>> +
>> + tbl_int = ACPI_ADD_PTR(struct acpi_mpam_interconnect_descriptor,
>> + tbl_int_tbl, sizeof(*tbl_int_tbl));
>> + cache_id = tbl_int->source_id;
>> +
>> + /* Unknown link type? */
>> + if (tbl_int->link_type != 0 && tbl_int->link_type == 1)
>> + return 0;
>> +
>> + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_UNKNOWN,
>> + 64 + tbl_int->link_type, cache_id);
>> default:
>> /* These get discovered later and are treated as unknown */
>> return 0;
>> @@ -150,7 +235,7 @@ int acpi_mpam_parse_resources(struct mpam_msc *msc,
>> return -EINVAL;
>> }
>>
>> - err = acpi_mpam_parse_resource(msc, resource);
>> + err = acpi_mpam_parse_resource(tbl_msc, msc, resource);
>> if (err)
>> return err;
>>
>
^ permalink raw reply
* Re: [PATCH v3 1/3] iio: adc: xilinx-ams: fix out-of-bounds channel lookup in event handling
From: Jonathan Cameron @ 2026-05-12 15:54 UTC (permalink / raw)
To: Guilherme Ivo Bozi
Cc: Salih Erim, Conall O'Griofa, Michal Simek, David Lechner,
Nuno Sá, Andy Shevchenko, linux-iio, linux-arm-kernel,
linux-kernel
In-Reply-To: <CAJgF-xum3OQ36keRW5gCnTTbnUhsHZUzL41xKn0hjJ3GqgyOZg@mail.gmail.com>
On Tue, 12 May 2026 12:40:05 -0300
Guilherme Ivo Bozi <guilherme.bozi@usp.br> wrote:
> Hi Salih,
>
> Replies are inline.
>
> On Tue, May 12, 2026 at 11:22 AM Salih Erim <salih.erim@amd.com> wrote:
> >
> > Hi Guilherme,
> >
> > Replies are inline.
> >
> > On 4/14/2026 11:40 PM, Guilherme Ivo Bozi wrote:
> > > ams_event_to_channel() may return a pointer past the end of
> > > dev->channels when no matching scan_index is found. This can lead
> > > to invalid memory access in ams_handle_event().
> > >
> > > Add a bounds check in ams_event_to_channel() and return NULL when
> > > no channel is found. Also guard the caller to safely handle this
> > > case.
> > >
> > > Fixes: d5c70627a794 ("iio: adc: Add Xilinx AMS driver")
> > > Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
> > > ---
> > > drivers/iio/adc/xilinx-ams.c | 5 +++++
> > > 1 file changed, 5 insertions(+)
> > >
> > > diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
> > > index 124470c92529..6191cd1b29a5 100644
> > > --- a/drivers/iio/adc/xilinx-ams.c
> > > +++ b/drivers/iio/adc/xilinx-ams.c
> > > @@ -871,6 +871,9 @@ static const struct iio_chan_spec *ams_event_to_channel(struct iio_dev *dev,
> > > if (dev->channels[i].scan_index == scan_index)
> > > break;
> > >
> > > + if (i == dev->num_channels)
> > > + return NULL;
> > > +
> > The added lines use spaces for indentation instead of tabs.
> I checked both locally and the raw mbox from lore.kernel.org, and the
> indentation uses TAB characters consistently (^I in the diff).
>
> To verify, I inspected the relevant hunk using cat -A:
>
> ^I^Iif (dev->channels[i].scan_index == scan_index)
> ^I^I^Ibreak;
>
> +^Iif (i == dev->num_channels)
> +^I^Ireturn NULL;
>
> ^Ireturn &dev->channels[i];
>
> I could not observe any indentation issues locally or from the raw mbox.
FWIW they look good to me as well. Salih, I'd guess you have a local issue.
b4 (on git.kernel.org) is really handy for ensuring none of those occur!
Jonathan
>
> >
> > Salih
> >
>
> --
> Guilherme Ivo
^ permalink raw reply
* Re: [PATCH v17 24/24] KVM: selftests: Add guest_memfd testcase to fault-in on !mmap()'d memory
From: Sean Christopherson @ 2026-05-12 15:53 UTC (permalink / raw)
To: Zenghui Yu
Cc: Zenghui Yu, Paolo Bonzini, Marc Zyngier, Oliver Upton, kvm,
linux-arm-kernel, kvmarm, linux-kernel, Ira Weiny, Gavin Shan,
Shivank Garg, Vlastimil Babka, Xiaoyao Li, David Hildenbrand,
Fuad Tabba, Ackerley Tng, Tao Chan, James Houghton
In-Reply-To: <c17d864a-42fc-afbe-345e-c728e2735d0c@huawei.com>
On Tue, May 12, 2026, Zenghui Yu wrote:
> Hi Sean,
>
> On 2026/4/18 0:47, Sean Christopherson wrote:
> >
> > Does this fix things for you? If so, I'll send a proper patch.
> >
> > diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c
> > index ec7644aae999..c682bda722f9 100644
> > --- a/tools/testing/selftests/kvm/guest_memfd_test.c
> > +++ b/tools/testing/selftests/kvm/guest_memfd_test.c
> > @@ -510,9 +510,15 @@ static void test_guest_memfd_guest(void)
> > "Default VM type should support INIT_SHARED, supported flags = 0x%x",
> > vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_FLAGS));
> >
> > + /*
> > + * Use the guest's page size for all accesses, e.g. to avoid having to
> > + * map multiple pages, but create the guest_memfd instance with the max
> > + * of the host or guest page size, as KVM requires gmem files to be
> > + * aligned to the host page size.
> > + */
> > size = vm->page_size;
> > - fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP |
> > - GUEST_MEMFD_FLAG_INIT_SHARED);
> > + fd = vm_create_guest_memfd(vm, max(size, page_size), GUEST_MEMFD_FLAG_MMAP |
> > + GUEST_MEMFD_FLAG_INIT_SHARED);
> > vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size, NULL, fd, 0);
> >
> > mem = kvm_mmap(size, PROT_READ | PROT_WRITE, MAP_SHARED, fd);
>
> This results in another failure at
>
> | vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size,
> NULL, fd, 0);
Gah, the memslot size also needs to be a multiple of the host page size. I
actually tested on a CONFIG_ARM64_64K_PAGES=y kernel this time, patch incoming...
Thanks!
^ permalink raw reply
* Re: [PATCH v3 3/3] iio: adc: xilinx-ams: refactor alarm mapping to table-driven approach
From: Guilherme Ivo Bozi @ 2026-05-12 15:46 UTC (permalink / raw)
To: Salih Erim
Cc: Conall O'Griofa, Jonathan Cameron, Michal Simek,
David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
linux-arm-kernel, linux-kernel
In-Reply-To: <e84d98dd-c81c-418d-8cbe-5867f8bdd4c3@amd.com>
Hi Salih,
On Tue, May 12, 2026 at 11:34 AM Salih Erim <salih.erim@amd.com> wrote:
>
> Hi,
>
> On 4/14/2026 11:40 PM, Guilherme Ivo Bozi wrote:
> > Replace multiple open-coded switch statements that map between
> > scan_index, alarm bits, and register offsets with a centralized
> > table-driven approach.
> >
> > Introduce a struct-based alarm_map to describe the relationship
> > between scan indices and alarm offsets, and add a helper to
> > translate scan_index to event IDs. This removes duplicated logic
> > across ams_get_alarm_offset(), ams_event_to_channel(), and
> > ams_get_alarm_mask().
> >
> > The new approach improves maintainability, reduces code size,
> > and makes it easier to extend or modify alarm mappings in the
> > future, while preserving existing behavior.
> >
> > Signed-off-by: Guilherme Ivo Bozi <guilherme.bozi@usp.br>
> > ---
> > drivers/iio/adc/xilinx-ams.c | 161 +++++++++++++----------------------
> > 1 file changed, 58 insertions(+), 103 deletions(-)
>
> Two issues:
>
> 1) Same tabs-vs-spaces indentation problem as patches 1 and 2.
>
> 2) In ams_event_to_channel():
>
> > + if (event < 0 || event >= ARRAY_SIZE(alarm_map))
> > + return NULL;
>
> The 'event' parameter is u32, so 'event < 0' is always false.
> Either drop the < 0 check or change the parameter type to int
> if you intend to handle negative values.
You are correct regarding the u32 type -- the event < 0 check is
unnecessary. I will remove it in the next revision.
>
> Salih
--
Guilherme Ivo
^ permalink raw reply
* Re: [PATCH v7 2/4] firmware: ti_sci: add support for restoring IRQs during resume
From: Thomas Richard @ 2026-05-12 15:44 UTC (permalink / raw)
To: Nishanth Menon
Cc: Tero Kristo, Santosh Shilimkar, Michael Turquette, Stephen Boyd,
Gregory CLEMENT, richard.genoud, Udit Kumar, Abhash Kumar,
Thomas Petazzoni, linux-arm-kernel, linux-kernel, linux-clk,
Dhruva Gole, Kendall Willis
In-Reply-To: <20260506141508.2bko3ntcv7rkqfvn@certainty>
Hello Nishanth,
On 5/6/26 4:15 PM, Nishanth Menon wrote:
> On 10:35-20260506, Thomas Richard (TI) wrote:
>> Some DM-Firmware are not able to restore the IRQ context after a
>> suspend-resume. The IRQ_CONTEXT_LOST firmware capability has been
>> introduced to identify this characteristic. In this case the
>> responsibility is delegated to the ti_sci driver, which maintains an
>> internal list of all requested IRQs. This list is updated on each
>> set()/free() operation, and all IRQs are restored during the resume_noirq()
>> phase.
>>
>> Reviewed-by: Dhruva Gole <d-gole@ti.com>
>> Reviewed-by: Kendall Willis <k-willis@ti.com>
>> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
>> ---
>
> coccicheck reports two additional warnings at this patch:
> +drivers/firmware/ti_sci.c:2495:1-7: preceding lock on line 2454
> +drivers/firmware/ti_sci.c:2420:1-7: preceding lock on line 2378
I do not see the potential deadlock in set_irq() and free_irq().
I guess it is a false positive.
>
>> drivers/firmware/ti_sci.c | 201 +++++++++++++++++++++++++++++++++++++++++++---
>> drivers/firmware/ti_sci.h | 2 +
>> 2 files changed, 191 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
>> index eaeaaae94142..531ac3aa38b8 100644
>> --- a/drivers/firmware/ti_sci.c
>> +++ b/drivers/firmware/ti_sci.c
>> @@ -12,11 +12,13 @@
>> #include <linux/cpu.h>
>> #include <linux/debugfs.h>
>> #include <linux/export.h>
>> +#include <linux/hashtable.h>
>> #include <linux/io.h>
>> #include <linux/iopoll.h>
>> #include <linux/kernel.h>
>> #include <linux/mailbox_client.h>
>> #include <linux/module.h>
>> +#include <linux/mutex.h>
>> #include <linux/of.h>
>> #include <linux/of_platform.h>
>> #include <linux/platform_device.h>
>> @@ -87,6 +89,16 @@ struct ti_sci_desc {
>> int max_msg_size;
>> };
>>
>> +/**
>> + * struct ti_sci_irq - Description of allocated irqs
>> + * @node: Link to hash table
>> + * @desc: Description of the irq
>> + */
>> +struct ti_sci_irq {
>> + struct hlist_node node;
>> + struct ti_sci_msg_req_manage_irq desc;
>> +};
>> +
>> /**
>> * struct ti_sci_info - Structure representing a TI SCI instance
>> * @dev: Device pointer
>> @@ -101,6 +113,8 @@ struct ti_sci_desc {
>> * @chan_rx: Receive mailbox channel
>> * @minfo: Message info
>> * @node: list head
>> + * @irqs: List of allocated irqs
>> + * @irq_lock: Protection for irq hash list
>> * @host_id: Host ID
>> * @fw_caps: FW/SoC low power capabilities
>> * @users: Number of users of this instance
>> @@ -118,6 +132,8 @@ struct ti_sci_info {
>> struct mbox_chan *chan_rx;
>> struct ti_sci_xfers_info minfo;
>> struct list_head node;
>> + DECLARE_HASHTABLE(irqs, 8);
>> + struct mutex irq_lock;
>
> No action needed: checkpatch flags this as not documented, when it is
> clearly documented above.
>
>> u8 host_id;
>> u64 fw_caps;
>> /* protected by ti_sci_list_mutex */
>> @@ -2301,6 +2317,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
>> return ret;
>> }
>>
>> +/**
>> + * ti_sci_irq_hash() - Helper API to compute irq hash for the hash table.
>> + * @irq: irq to hash
>> + *
>> + * Return: the computed hash value.
>> + */
>> +static int ti_sci_irq_hash(struct ti_sci_msg_req_manage_irq *irq)
>> +{
>> + return irq->src_id ^ irq->src_index;
>> +}
>> +
>> +/**
>> + * ti_sci_irq_equal() - Helper API to compare two irqs (generic headers are not
>> + * compared)
>> + * @irq_a: irq_a to compare
>> + * @irq_b: irq_b to compare
>> + *
>> + * Return: true if the two irqs are equal, else false.
>> + */
>> +static bool ti_sci_irq_equal(struct ti_sci_msg_req_manage_irq *irq_a,
>> + struct ti_sci_msg_req_manage_irq *irq_b)
>> +{
>> + return !memcmp(&irq_a->valid_params, &irq_b->valid_params,
>> + sizeof(*irq_a) - sizeof(irq_a->hdr));
>> +}
>> +
>> /**
>> * ti_sci_set_irq() - Helper api to configure the irq route between the
>> * requested source and destination
>> @@ -2324,15 +2366,60 @@ static int ti_sci_set_irq(const struct ti_sci_handle *handle, u32 valid_params,
>> u16 dst_host_irq, u16 ia_id, u16 vint,
>> u16 global_event, u8 vint_status_bit, u8 s_host)
>> {
>> + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
>> + struct ti_sci_msg_req_manage_irq *desc;
>> + struct ti_sci_irq *irq;
>> + int ret;
>> +
>> + /*
>> + * Lock for set_irq() and free_irq() to keep the IRQ hash list
>> + * consistent only if MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST is set. Else
>> + * IRQ hash list is not used.
>> + */
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)
>> + mutex_lock(&info->irq_lock);
>> +
>> pr_debug("%s: IRQ set with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
>> __func__, valid_params, src_id, src_index,
>> dst_id, dst_host_irq, ia_id, vint, global_event,
>> vint_status_bit);
>>
>> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
>> - dst_id, dst_host_irq, ia_id, vint,
>> - global_event, vint_status_bit, s_host,
>> - TI_SCI_MSG_SET_IRQ);
>> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
>> + dst_id, dst_host_irq, ia_id, vint,
>> + global_event, vint_status_bit, s_host,
>> + TI_SCI_MSG_SET_IRQ);
>> +
>> + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST))
>> + goto end;
>> +
>> + irq = kzalloc_obj(*irq, GFP_KERNEL);
>> + if (!irq) {
>> + ti_sci_manage_irq(handle, valid_params, src_id, src_index,
>> + dst_id, dst_host_irq, ia_id, vint,
>> + global_event, vint_status_bit, s_host,
>> + TI_SCI_MSG_FREE_IRQ);
>> + ret = -ENOMEM;
>> + goto end;
>> + }
>> +
>> + desc = &irq->desc;
>> + desc->valid_params = valid_params;
>> + desc->src_id = src_id;
>> + desc->src_index = src_index;
>> + desc->dst_id = dst_id;
>> + desc->dst_host_irq = dst_host_irq;
>> + desc->ia_id = ia_id;
>> + desc->vint = vint;
>> + desc->global_event = global_event;
>> + desc->vint_status_bit = vint_status_bit;
>> + desc->secondary_host = s_host;
>> +
>> + hash_add(info->irqs, &irq->node, ti_sci_irq_hash(desc));
>> +
>> +end:
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)
>> + mutex_unlock(&info->irq_lock);
>> + return ret;
>> }
>>
>> /**
>> @@ -2358,15 +2445,56 @@ static int ti_sci_free_irq(const struct ti_sci_handle *handle, u32 valid_params,
>> u16 dst_host_irq, u16 ia_id, u16 vint,
>> u16 global_event, u8 vint_status_bit, u8 s_host)
>> {
>> + struct ti_sci_info *info = handle_to_ti_sci_info(handle);
>> + struct ti_sci_msg_req_manage_irq irq_desc;
>> + struct device *dev = info->dev;
>> + struct ti_sci_irq *this_irq;
>> + struct hlist_node *tmp_node;
>> + int ret;
>> +
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)
>> + mutex_lock(&info->irq_lock);
>> +
>> pr_debug("%s: IRQ release with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
>> __func__, valid_params, src_id, src_index,
>> dst_id, dst_host_irq, ia_id, vint, global_event,
>> vint_status_bit);
>>
>> - return ti_sci_manage_irq(handle, valid_params, src_id, src_index,
>> - dst_id, dst_host_irq, ia_id, vint,
>> - global_event, vint_status_bit, s_host,
>> - TI_SCI_MSG_FREE_IRQ);
>> + ret = ti_sci_manage_irq(handle, valid_params, src_id, src_index,
>> + dst_id, dst_host_irq, ia_id, vint,
>> + global_event, vint_status_bit, s_host,
>> + TI_SCI_MSG_FREE_IRQ);
>> +
>> + if (ret || !(info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST))
>> + goto end;
>> +
>> + irq_desc.valid_params = valid_params;
>> + irq_desc.src_id = src_id;
>> + irq_desc.src_index = src_index;
>> + irq_desc.dst_id = dst_id;
>> + irq_desc.dst_host_irq = dst_host_irq;
>> + irq_desc.ia_id = ia_id;
>> + irq_desc.vint = vint;
>> + irq_desc.global_event = global_event;
>> + irq_desc.vint_status_bit = vint_status_bit;
>> + irq_desc.secondary_host = s_host;
>> +
>> + hash_for_each_possible_safe(info->irqs, this_irq, tmp_node, node,
>> + ti_sci_irq_hash(&irq_desc)) {
>> + if (ti_sci_irq_equal(&irq_desc, &this_irq->desc)) {
>> + hlist_del(&this_irq->node);
>> + kfree(this_irq);
>> + goto end;
>> + }
>> + }
>> +
>> + dev_warn(dev, "%s: should not be here, IRQ was not found in hash list\n",
>> + __func__);
>> +
>> +end:
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST)
>> + mutex_unlock(&info->irq_lock);
>> + return ret;
>> }
>>
>> /**
>> @@ -3847,7 +3975,10 @@ static int ti_sci_suspend_noirq(struct device *dev)
>> static int ti_sci_resume_noirq(struct device *dev)
>> {
>> struct ti_sci_info *info = dev_get_drvdata(dev);
>> - int ret = 0;
>> + struct ti_sci_msg_req_manage_irq *irq_desc;
>> + struct ti_sci_irq *irq;
>> + struct hlist_node *tmp_node;
>> + int ret = 0, err = 0, i;
>> u32 source;
>> u64 time;
>> u8 pin;
>> @@ -3859,13 +3990,50 @@ static int ti_sci_resume_noirq(struct device *dev)
>> return ret;
>> }
>>
>> + switch (pm_suspend_target_state) {
>> + case PM_SUSPEND_MEM:
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) {
>> + hash_for_each_safe(info->irqs, i, tmp_node, irq, node) {
>> + irq_desc = &irq->desc;
>> + ret = ti_sci_manage_irq(&info->handle,
>> + irq_desc->valid_params,
>> + irq_desc->src_id,
>> + irq_desc->src_index,
>> + irq_desc->dst_id,
>> + irq_desc->dst_host_irq,
>> + irq_desc->ia_id,
>> + irq_desc->vint,
>> + irq_desc->global_event,
>> + irq_desc->vint_status_bit,
>> + irq_desc->secondary_host,
>> + TI_SCI_MSG_SET_IRQ);
>> + if (ret) {
>> + dev_err(dev, "failed to restore IRQ with valid_params = 0x%x from src = %d, index = %d, to dst = %d, irq = %d,via ia_id = %d, vint = %d, global event = %d,status_bit = %d\n",
>
> space before via? overall this print is needed, but a bit umm.. we have
> similar ones already..
Yes I wanted to have consistent messages.
Will fix the missing space.
>
>> + irq_desc->valid_params,
>> + irq_desc->src_id,
>> + irq_desc->src_index,
>> + irq_desc->dst_id,
>> + irq_desc->dst_host_irq,
>> + irq_desc->ia_id,
>> + irq_desc->vint,
>> + irq_desc->global_event,
>> + irq_desc->vint_status_bit);
>> + err = ret;
>> + }
>> + }
>> + }
>> + break;
>> + default:
>> + break;
>> + }
>> +
>> ret = ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time, &pin, &mode);
>> /* Do not fail to resume on error as the wake reason is not critical */
>> if (!ret)
>> dev_info(dev, "ti_sci: wakeup source:0x%x, pin:0x%x, mode:0x%x\n",
>> source, pin, mode);
>>
>> - return 0;
>> + return err;
>> }
>>
>> static void ti_sci_pm_complete(struct device *dev)
>> @@ -4014,13 +4182,14 @@ static int ti_sci_probe(struct platform_device *pdev)
>> }
>>
>> ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps);
>> - dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s\n",
>> + dev_dbg(dev, "Detected firmware capabilities: %s%s%s%s%s%s%s\n",
>> info->fw_caps & MSG_FLAG_CAPS_GENERIC ? "Generic" : "",
>> info->fw_caps & MSG_FLAG_CAPS_LPM_PARTIAL_IO ? " Partial-IO" : "",
>> info->fw_caps & MSG_FLAG_CAPS_LPM_DM_MANAGED ? " DM-Managed" : "",
>> info->fw_caps & MSG_FLAG_CAPS_LPM_ABORT ? " LPM-Abort" : "",
>> info->fw_caps & MSG_FLAG_CAPS_IO_ISOLATION ? " IO-Isolation" : "",
>> - info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : ""
>> + info->fw_caps & MSG_FLAG_CAPS_LPM_BOARDCFG_MANAGED ? " BoardConfig-Managed" : "",
>> + info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST ? " IRQ-Context-Lost" : ""
>> );
>>
>> ti_sci_setup_ops(info);
>> @@ -4053,6 +4222,14 @@ static int ti_sci_probe(struct platform_device *pdev)
>> list_add_tail(&info->node, &ti_sci_list);
>> mutex_unlock(&ti_sci_list_mutex);
>>
>> + if (info->fw_caps & MSG_FLAG_CAPS_LPM_IRQ_CONTEXT_LOST) {
>> + ret = devm_mutex_init(dev, &info->irq_lock);
>> + if (ret)
>> + return ret;
>
> If devm_mutex_init() fails, the function returns directly rather than
> going through the out: label. All other error paths after the mailbox
> channel allocations use goto out, which calls mbox_free_channel() for
> both channels. Since mbox_request_channel_byname() is not a devm
> allocation, those channels would not be freed by the devm cleanup path
> on probe failure.
>
> Does this leak info->chan_tx and info->chan_rx when devm_mutex_init()
> returns an error?
Indeed we should go to 'out'.
Best Regards,
Thomas
^ permalink raw reply
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