Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp2984951imu; Sun, 9 Dec 2018 14:18:34 -0800 (PST) X-Google-Smtp-Source: AFSGD/W80k42U85413jpG2ZRV38D5Ab7J1VBt3RLivfTaKT0r0z60ON5fxzC7mdquIwAD1A2oKyr X-Received: by 2002:a17:902:4c85:: with SMTP id b5mr9442433ple.226.1544393914424; Sun, 09 Dec 2018 14:18:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544393914; cv=none; d=google.com; s=arc-20160816; b=fljHX2YKVSf+j54uW4ZgNm3rXO80a1tl8RQI4WLsAh4GWtbOitil4CM+bHj8iVFEgt l9JI8IptHeIUZl7+uQafGBAXHLOONyuhSbbfxzoLdndz/W6OVWnzTvHtbGYdifJhi5dI AZJCgod3VZZimZkQFP2DvJOSZcUxr+/ymAWZ5UjUYMIDIdCeJSGR1mGc1qTP5rUcJLfW rgGNaaEQSMzGX/5CZ3hFVLxmhKtZFL72NoQXKSmJ7ePd85gCg87tiMZhN3D7g2SBxZVG ahCxXL20O04vRU9SC1Di3JlvRi+iWI9fop6toXxlHY3E6mAjlmqn6QeRqecJiwq7BWOe Z2aA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=8+THkm+LrrBdCtMd52pkg3Po/9ZPy9mnXCxCK0xKMwA=; b=tSyawBOZta+NP39aGwjglRAUDGQj/XtgryECCzEjA5MGAG4mY6Q7LnypPrnFxKqaHN FqFg5NT+IZtCvJ8RnT6LzVhXop3NY1hNd/NjgcUQqrilYkNFOpfyb2LNGhv644eNPwv7 lXFtYk7SipfreaUADWELFnHlTbIomWeP7xrS+7fFUOCxRdRPE9wdYWQjafJ75PJeMZX2 M4y4YQLprINRaVlAS1lNFAzThcyIGfXTTez4gy2lMgWs/cep0Vx1b3Y00gP5Z8AMJCFU Pbt2uKxgpSgQNrm3/9kmfYq5p2uCY3ebbdO9aqUm4Ti6NFxCO+UTEk5O8gAecV1Tf+n3 RlGw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p11si8312531plo.363.2018.12.09.14.18.19; Sun, 09 Dec 2018 14:18:34 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728441AbeLIWNs (ORCPT + 99 others); Sun, 9 Dec 2018 17:13:48 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:37960 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727125AbeLIWNq (ORCPT ); Sun, 9 Dec 2018 17:13:46 -0500 Received: from pub.yeoldevic.com ([81.174.156.145] helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gW735-0002ir-7J; Sun, 09 Dec 2018 21:55:39 +0000 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1gW72g-0003VQ-Ap; Sun, 09 Dec 2018 21:55:14 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Laurent Pinchart" , "Mark Brown" , "Geert Uytterhoeven" Date: Sun, 09 Dec 2018 21:50:33 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) X-Patchwork-Hint: ignore Subject: [PATCH 3.16 204/328] spi: rspi: Fix leaking of unused DMA descriptors In-Reply-To: X-SA-Exim-Connect-IP: 81.174.156.145 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.62-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Geert Uytterhoeven commit 3819bc8752367eae0d72fa1c473dc88ea45631a7 upstream. If dmaengine_prep_slave_sg() or dmaengine_submit() fail, we may leak unused DMA descriptors. As per Documentation/dmaengine.txt, once a DMA descriptor has been obtained, it must be submitted. Hence: - First prepare and submit all DMA descriptors, - Prepare the SPI controller for DMA, - Start DMA by calling dma_async_issue_pending(), - Make sure to call dmaengine_terminate_all() on all descriptors that haven't completed. Reported-by: Laurent Pinchart Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown Signed-off-by: Ben Hutchings --- drivers/spi/spi-rspi.c | 94 ++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 36 deletions(-) --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -472,25 +472,52 @@ static int rspi_dma_transfer(struct rspi dma_cookie_t cookie; int ret; - if (tx) { - desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, - tx->sgl, tx->nents, DMA_TO_DEVICE, - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc_tx) - goto no_dma; - - irq_mask |= SPCR_SPTIE; - } + /* First prepare and submit the DMA request(s), as this may fail */ if (rx) { desc_rx = dmaengine_prep_slave_sg(rspi->master->dma_rx, rx->sgl, rx->nents, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc_rx) - goto no_dma; + if (!desc_rx) { + ret = -EAGAIN; + goto no_dma_rx; + } + + desc_rx->callback = rspi_dma_complete; + desc_rx->callback_param = rspi; + cookie = dmaengine_submit(desc_rx); + if (dma_submit_error(cookie)) { + ret = cookie; + goto no_dma_rx; + } irq_mask |= SPCR_SPRIE; } + if (tx) { + desc_tx = dmaengine_prep_slave_sg(rspi->master->dma_tx, + tx->sgl, tx->nents, DMA_TO_DEVICE, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc_tx) { + ret = -EAGAIN; + goto no_dma_tx; + } + + if (rx) { + /* No callback */ + desc_tx->callback = NULL; + } else { + desc_tx->callback = rspi_dma_complete; + desc_tx->callback_param = rspi; + } + cookie = dmaengine_submit(desc_tx); + if (dma_submit_error(cookie)) { + ret = cookie; + goto no_dma_tx; + } + + irq_mask |= SPCR_SPTIE; + } + /* * DMAC needs SPxIE, but if SPxIE is set, the IRQ routine will be * called. So, this driver disables the IRQ while DMA transfer. @@ -503,34 +530,24 @@ static int rspi_dma_transfer(struct rspi rspi_enable_irq(rspi, irq_mask); rspi->dma_callbacked = 0; - if (rx) { - desc_rx->callback = rspi_dma_complete; - desc_rx->callback_param = rspi; - cookie = dmaengine_submit(desc_rx); - if (dma_submit_error(cookie)) - return cookie; + /* Now start DMA */ + if (rx) dma_async_issue_pending(rspi->master->dma_rx); - } - if (tx) { - if (rx) { - /* No callback */ - desc_tx->callback = NULL; - } else { - desc_tx->callback = rspi_dma_complete; - desc_tx->callback_param = rspi; - } - cookie = dmaengine_submit(desc_tx); - if (dma_submit_error(cookie)) - return cookie; + if (tx) dma_async_issue_pending(rspi->master->dma_tx); - } ret = wait_event_interruptible_timeout(rspi->wait, rspi->dma_callbacked, HZ); if (ret > 0 && rspi->dma_callbacked) ret = 0; - else if (!ret) + else if (!ret) { + dev_err(&rspi->master->dev, "DMA timeout\n"); ret = -ETIMEDOUT; + if (tx) + dmaengine_terminate_all(rspi->master->dma_tx); + if (rx) + dmaengine_terminate_all(rspi->master->dma_rx); + } rspi_disable_irq(rspi, irq_mask); @@ -541,11 +558,16 @@ static int rspi_dma_transfer(struct rspi return ret; -no_dma: - pr_warn_once("%s %s: DMA not available, falling back to PIO\n", - dev_driver_string(&rspi->master->dev), - dev_name(&rspi->master->dev)); - return -EAGAIN; +no_dma_tx: + if (rx) + dmaengine_terminate_all(rspi->master->dma_rx); +no_dma_rx: + if (ret == -EAGAIN) { + pr_warn_once("%s %s: DMA not available, falling back to PIO\n", + dev_driver_string(&rspi->master->dev), + dev_name(&rspi->master->dev)); + } + return ret; } static void rspi_receive_init(const struct rspi_data *rspi)