From nobody Sun May 24 18:41:55 2026 Received: from mail-pf1-f172.google.com (mail-pf1-f172.google.com [209.85.210.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F242638E8BB for ; Fri, 22 May 2026 12:40:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779453659; cv=none; b=jNXgdWtASTDVfZ9zb5YRXc+Kf7h6igcFsxVYe3DPEN7z+UKWAkcra8kFc71cUDFbsi6I9Uftzy1ZyymIX33Juebmy4fyGEYOc/CqtSo9r8yD9vTCAd2k1JqMOJ+M7+Uu013UQCLQ/3ovqNjCcEFNVKoJElgATQ01IBLnIcIVBKU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779453659; c=relaxed/simple; bh=Y82jaR7ig01C99YVTX1uP7k3+xb7iSdiU2qTIciu+vY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=jgBiicAhsVSP3hUjgYAUIIRD+b6IlXAdjwo1aEzIEAyGpXCi14zZ2Wek5GNd/kD5NNVvOC3CwhDKZa1SQOQKCoR66G1ICwvWunpIejcx01W/fqZVzbH36QOuWHT6Bm/KQK4uvWzKnUJgIaNQ2aTCWBMXAanSdN/r0LtWJCA7Zy8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=ScK4BHmV; arc=none smtp.client-ip=209.85.210.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="ScK4BHmV" Received: by mail-pf1-f172.google.com with SMTP id d2e1a72fcca58-836ed29d1e5so3223105b3a.2 for ; Fri, 22 May 2026 05:40:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779453657; x=1780058457; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=JHMw4rHowryIGHkjcmpjPUf8sGdPW4drldezm1GiZm0=; b=ScK4BHmVAss6hHZ337IJm5+jVB7ebmdiBln59utabdbF3vI6wxvcIsTQ3pgazCklYl Q70HbrGL2IsULOEIFP+2GNc7xHj5dqanOWXAoZlEiqitagW462kZmiFW1Z84jTzoctn9 4wG0zZPooChyVnhoX7jEakTAnXFrKxNILrxWmjKa3yp03HR5Z9Y5vnmR6t32+cNYN6Cf UwAKeG8lRyJEFhs1udwMIKUej+nNegs7gsSk+WVfWzVj6IeWAnOnzzJigakupkoqbn+N wPcBc5l1dQpUm2ZaXKI3LJdfDf/We8ke8bBh8kRUVZ/GNd1WOuYLq9uW+IDb9FG3cIWi +cKA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779453657; x=1780058457; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=JHMw4rHowryIGHkjcmpjPUf8sGdPW4drldezm1GiZm0=; b=CFcdhf3JdRiKF0GCX1XUyVxj7xOjp/tNnXtpK0s8t0PnfHB40IlCbOZsNQKlPEsTSL xu9ADUbZaWGF73qfjcBdBkKVAO2N0G8ktJ7f+B05yKGDSfcl49sciVKGuoRDgLgnxXLN SGGjhML8UAxEYbo522y/KDikpy6jWLR6Fcukettm5EBCAU0vjWDVjlH6vJQLoXsPWygv 5BQniszjes6wBAoULbuIZOuZlhA31Y90OawLlUijv7pkEcDfmK0ggIrqles/KvK4I7nZ 8SJ+EZUzapb7K5osPrhBV89TsXaCWOLdGzZc8PRgCzC+Ub6DvclPIxYxu2yiTlVb5jGm tsng== X-Forwarded-Encrypted: i=1; AFNElJ+/kvzfuufKsC4zj+Lkeu97rpdq2l+7pePJGoZkSnKOBYs8QzKgUuEenA5rmude7aBNUUl3A6kz/jW4U/I=@vger.kernel.org X-Gm-Message-State: AOJu0Ywa2PJm1fSiZ6nBbbo4zN84BdozQjtdvRKVrEUm+lH3cKaAz3BZ OnaqyU7eKBUUNT3bjKN7OKtTSAONEzYTwK2Sa4/3l5nvCE/57lIeCQiA X-Gm-Gg: Acq92OHZ/Hwl522CcQWqXsMr0l8gVu+DEzzYYJ41ryJLPZRGPz+5yv73PXUWDPc9Nps 830OGcnUK9OZFl6nQcmYJGeyL2p/ug3hpCqtfVIa18ELT0PS1I/AQA0CX3E6wG3f5gJRh2mgu64 JAR0Jpe4ewaLINknDSNjM6Ns0hihNvEtWqBlAHzhtn1jSewkk3S21lGHlwor4yxyqPE/WQYl51e 77rOEDOlkeEAspPHIdKg2IyadO07DTvzpxhL8aUrM9HA/1CqvYTXgGTuHS0S2A/QKI92nPy2335 HBbmwJP2ATeHRH7qmruIl7/VslRjpEqYVK8ECTYaLYNUDPkX2ARzsk0/9KI2ArMtGelpnN0+A6j 3QAn9OGTvDWho0ar7usOVvYFWTsbtN/hB8ayHz62cQ1uDM9GciJBwBxdlQcxsD5m+1uX6s5tpEo DZGjzfJ1vW9LH4Uv6BlKJRTqktrC0orB8N2dXEeo1ljPu4IBKYe4x89r/W86yRxca9lC7jDQV9u XUmp3t98RbHqksdDw== X-Received: by 2002:a05:6a00:1c8a:b0:83a:3155:c5e9 with SMTP id d2e1a72fcca58-8415f2dade2mr3857383b3a.6.1779453656944; Fri, 22 May 2026 05:40:56 -0700 (PDT) Received: from junjungu-PC.localdomain ([223.166.246.30]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-84164aee7f5sm1929461b3a.14.2026.05.22.05.40.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 May 2026 05:40:55 -0700 (PDT) From: Felix Gu Date: Fri, 22 May 2026 20:40:48 +0800 Subject: [PATCH v3] spi: atmel: fix DMA channel and bounce buffer leaks Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260522-atmel-v3-1-23f8c6e6aa43@gmail.com> X-B4-Tracking: v=1; b=H4sIAM9OEGoC/12Nyw6CMBQFf4V0bU0fcGtc+R/GRVsuUAPUtNhoC P8uxZgQl5OcmTOTiMFhJOdiJgGTi86PK8hDQWynxxapq1cmgglgFQeqpwF7CjUYxiuGRiFZt4+ AjXttnevty/Fp7minLOdF5+Lkw3s7Sjzv/puJU0ZBlY0pFVO6gUs7aNcfrR9Ibiaxt9TPEpRTC fYkwSDIstpby7J8AGtuoqbiAAAA X-Change-ID: 20260516-atmel-6d6b0150eb7e To: Ryan Wanner , Mark Brown , Nicolas Ferre , Alexandre Belloni , Claudiu Beznea , Radu Pirea , Richard Genoud Cc: linux-spi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Felix Gu X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1779453651; l=7250; i=ustc.gu@gmail.com; h=from:subject:message-id; bh=Y82jaR7ig01C99YVTX1uP7k3+xb7iSdiU2qTIciu+vY=; b=+R9Ushno/vwtOe8P1yjlWaCnoC/axXRM26wAw3q+bNjUEGjdFxqaHTLkeRe8cxvvOzvhgomID 9Z1paZaF1J/AlSPXublvQaGFLTluZIsQ4maNSwnQBFkv0y4qiVQJDtp X-Developer-Key: i=ustc.gu@gmail.com; a=ed25519; pk=fjUXwmjchVN7Ja6KGP55IXOzFeCl9edaHoQIEUA+/hw= The original code set use_dma to false when dma_alloc_coherent() for bounce buffers failed, but DMA channels acquired earlier via atmel_spi_configure_dma() were never freed. When devm_request_irq() or clk_prepare_enable() failed later in probe, the driver also did not release DMA channels or bounce buffers already allocated. The out_free_dma error path released DMA channels but did not free the bounce buffers. Fix by moving bounce buffer allocation into atmel_spi_configure_dma() and registering the devres cleanup for DMA channels and bounce buffers. Fixes: a9889ed62d06 ("spi: atmel: Implements transfers with bounce buffer") Signed-off-by: Felix Gu --- Changes in v3: - Fix Mark's comment. - Link to v2: https://patch.msgid.link/20260517-atmel-v2-1-36c836be6345@gma= il.com Changes in v2: - Switch to devm-managed variants to fix Claudiu Beznea's comment. - Link to v1: https://patch.msgid.link/20260516-atmel-v1-0-674fb4707af6@gma= il.com To: Ryan Wanner To: Mark Brown To: Nicolas Ferre To: Alexandre Belloni To: Claudiu Beznea To: Radu Pirea Cc: linux-spi@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- drivers/spi/spi-atmel.c | 133 +++++++++++++++++++++++++-------------------= ---- 1 file changed, 68 insertions(+), 65 deletions(-) diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 25aa294631c8..c8012c82c3a7 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -559,6 +559,38 @@ static int atmel_spi_dma_slave_config(struct atmel_spi= *as, u8 bits_per_word) return err; } =20 +static void atmel_spi_release_dma(void *data) +{ + struct spi_controller *host =3D data; + struct atmel_spi *as =3D spi_controller_get_devdata(host); + struct device *dev =3D &as->pdev->dev; + + if (host->dma_tx) { + dma_release_channel(host->dma_tx); + host->dma_tx =3D NULL; + } + + if (host->dma_rx) { + dma_release_channel(host->dma_rx); + host->dma_rx =3D NULL; + } + + if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { + if (as->addr_tx_bbuf) { + dma_free_coherent(dev, SPI_MAX_DMA_XFER, + as->addr_tx_bbuf, + as->dma_addr_tx_bbuf); + as->addr_tx_bbuf =3D NULL; + } + if (as->addr_rx_bbuf) { + dma_free_coherent(dev, SPI_MAX_DMA_XFER, + as->addr_rx_bbuf, + as->dma_addr_rx_bbuf); + as->addr_rx_bbuf =3D NULL; + } + } +} + static int atmel_spi_configure_dma(struct spi_controller *host, struct atmel_spi *as) { @@ -569,7 +601,8 @@ static int atmel_spi_configure_dma(struct spi_controlle= r *host, if (IS_ERR(host->dma_tx)) { err =3D PTR_ERR(host->dma_tx); dev_dbg(dev, "No TX DMA channel, DMA is disabled\n"); - goto error_clear; + host->dma_tx =3D NULL; + return err; } =20 host->dma_rx =3D dma_request_chan(dev, "rx"); @@ -580,26 +613,45 @@ static int atmel_spi_configure_dma(struct spi_control= ler *host, * requested tx channel. */ dev_dbg(dev, "No RX DMA channel, DMA is disabled\n"); - goto error; + host->dma_rx =3D NULL; + goto err_release_dma; } =20 err =3D atmel_spi_dma_slave_config(as, 8); if (err) - goto error; + goto err_release_dma; + + if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { + as->addr_tx_bbuf =3D dma_alloc_coherent(dev, SPI_MAX_DMA_XFER, + &as->dma_addr_tx_bbuf, + GFP_KERNEL | GFP_DMA); + if (!as->addr_tx_bbuf) { + err =3D -ENOMEM; + goto err_release_dma; + } + + as->addr_rx_bbuf =3D dma_alloc_coherent(dev, SPI_MAX_DMA_XFER, + &as->dma_addr_rx_bbuf, + GFP_KERNEL | GFP_DMA); + if (!as->addr_rx_bbuf) { + err =3D -ENOMEM; + goto err_release_dma; + } + } + + err =3D devm_add_action_or_reset(dev, atmel_spi_release_dma, host); + if (err) + return err; =20 dev_info(&as->pdev->dev, - "Using %s (tx) and %s (rx) for DMA transfers\n", - dma_chan_name(host->dma_tx), - dma_chan_name(host->dma_rx)); + "Using %s (tx) and %s (rx) for DMA transfers\n", + dma_chan_name(host->dma_tx), dma_chan_name(host->dma_rx)); =20 return 0; -error: - if (!IS_ERR(host->dma_rx)) - dma_release_channel(host->dma_rx); - if (!IS_ERR(host->dma_tx)) - dma_release_channel(host->dma_tx); -error_clear: - host->dma_tx =3D host->dma_rx =3D NULL; + +err_release_dma: + atmel_spi_release_dma(host); + return err; } =20 @@ -611,18 +663,6 @@ static void atmel_spi_stop_dma(struct spi_controller *= host) dmaengine_terminate_all(host->dma_tx); } =20 -static void atmel_spi_release_dma(struct spi_controller *host) -{ - if (host->dma_rx) { - dma_release_channel(host->dma_rx); - host->dma_rx =3D NULL; - } - if (host->dma_tx) { - dma_release_channel(host->dma_tx); - host->dma_tx =3D NULL; - } -} - /* This function is called by the DMA driver from tasklet context */ static void dma_callback(void *data) { @@ -1581,30 +1621,6 @@ static int atmel_spi_probe(struct platform_device *p= dev) as->use_pdc =3D true; } =20 - if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { - as->addr_rx_bbuf =3D dma_alloc_coherent(&pdev->dev, - SPI_MAX_DMA_XFER, - &as->dma_addr_rx_bbuf, - GFP_KERNEL | GFP_DMA); - if (!as->addr_rx_bbuf) { - as->use_dma =3D false; - } else { - as->addr_tx_bbuf =3D dma_alloc_coherent(&pdev->dev, - SPI_MAX_DMA_XFER, - &as->dma_addr_tx_bbuf, - GFP_KERNEL | GFP_DMA); - if (!as->addr_tx_bbuf) { - as->use_dma =3D false; - dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, - as->addr_rx_bbuf, - as->dma_addr_rx_bbuf); - } - } - if (!as->use_dma) - dev_info(host->dev.parent, - " can not allocate dma coherent memory\n"); - } - if (as->caps.has_dma_support && !as->use_dma) dev_info(&pdev->dev, "Atmel SPI Controller using PIO only\n"); =20 @@ -1664,13 +1680,10 @@ static int atmel_spi_probe(struct platform_device *= pdev) out_free_dma: pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); - - if (as->use_dma) - atmel_spi_release_dma(host); - spi_writel(as, CR, SPI_BIT(SWRST)); spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ - clk_disable_unprepare(as->gclk); + if (as->gclk) + clk_disable_unprepare(as->gclk); out_disable_clk: clk_disable_unprepare(clk); =20 @@ -1687,18 +1700,8 @@ static void atmel_spi_remove(struct platform_device = *pdev) spi_unregister_controller(host); =20 /* reset the hardware and block queue progress */ - if (as->use_dma) { + if (as->use_dma) atmel_spi_stop_dma(host); - atmel_spi_release_dma(host); - if (IS_ENABLED(CONFIG_SOC_SAM_V4_V5)) { - dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, - as->addr_tx_bbuf, - as->dma_addr_tx_bbuf); - dma_free_coherent(&pdev->dev, SPI_MAX_DMA_XFER, - as->addr_rx_bbuf, - as->dma_addr_rx_bbuf); - } - } =20 spin_lock_irq(&as->lock); spi_writel(as, CR, SPI_BIT(SWRST)); --- base-commit: e98d21c170b01ddef366f023bbfcf6b31509fa83 change-id: 20260516-atmel-6d6b0150eb7e Best regards, -- =20 Felix Gu