From 89cc889a4404eea6f11e856f456d6e4f679a0d40 Mon Sep 17 00:00:00 2001 From: Xiaoyu Ye Date: Tue, 29 May 2018 17:03:55 -0700 Subject: [PATCH] asoc: wcd-spi: use CMA memory for TX and RX buffer instead of kzalloc In wcd-spi driver, the kzalloc is used to allocate memory for TX and RX buffer. Those allocations are order4 or order5, which could fail on some kernels. To avoid potential memory allocation failure, the CMA region is used for those allocations by dma_alloc_coherent API. Change-Id: I0a4d6c6b5e0e47f96187563272e63c3a006e469f Signed-off-by: Xiaoyu Ye --- asoc/codecs/wcd-spi.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/asoc/codecs/wcd-spi.c b/asoc/codecs/wcd-spi.c index 35b0d93b468a..145c4df69055 100644 --- a/asoc/codecs/wcd-spi.c +++ b/asoc/codecs/wcd-spi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */ #include @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -152,6 +153,10 @@ struct wcd_spi_priv { /* Buffers to hold memory used for transfers */ void *tx_buf; void *rx_buf; + + /* DMA handles for transfer buffers */ + dma_addr_t tx_dma; + dma_addr_t rx_dma; }; enum xfer_request { @@ -1371,17 +1376,20 @@ static int wcd_spi_component_bind(struct device *dev, spi_message_add_tail(&wcd_spi->xfer2[1], &wcd_spi->msg2); /* Pre-allocate the buffers */ - wcd_spi->tx_buf = kzalloc(WCD_SPI_RW_MAX_BUF_SIZE, - GFP_KERNEL | GFP_DMA); + wcd_spi->tx_buf = dma_zalloc_coherent(&spi->dev, + WCD_SPI_RW_MAX_BUF_SIZE, + &wcd_spi->tx_dma, GFP_KERNEL); if (!wcd_spi->tx_buf) { ret = -ENOMEM; goto done; } - wcd_spi->rx_buf = kzalloc(WCD_SPI_RW_MAX_BUF_SIZE, - GFP_KERNEL | GFP_DMA); + wcd_spi->rx_buf = dma_zalloc_coherent(&spi->dev, + WCD_SPI_RW_MAX_BUF_SIZE, + &wcd_spi->rx_dma, GFP_KERNEL); if (!wcd_spi->rx_buf) { - kfree(wcd_spi->tx_buf); + dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE, + wcd_spi->tx_buf, wcd_spi->tx_dma); wcd_spi->tx_buf = NULL; ret = -ENOMEM; goto done; @@ -1408,8 +1416,10 @@ static void wcd_spi_component_unbind(struct device *dev, spi_transfer_del(&wcd_spi->xfer2[0]); spi_transfer_del(&wcd_spi->xfer2[1]); - kfree(wcd_spi->tx_buf); - kfree(wcd_spi->rx_buf); + dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE, + wcd_spi->tx_buf, wcd_spi->tx_dma); + dma_free_coherent(&spi->dev, WCD_SPI_RW_MAX_BUF_SIZE, + wcd_spi->rx_buf, wcd_spi->rx_dma); wcd_spi->tx_buf = NULL; wcd_spi->rx_buf = NULL; } @@ -1445,6 +1455,7 @@ static int wcd_spi_probe(struct spi_device *spi) mutex_init(&wcd_spi->xfer_mutex); INIT_DELAYED_WORK(&wcd_spi->clk_dwork, wcd_spi_clk_work); init_completion(&wcd_spi->resume_comp); + arch_setup_dma_ops(&spi->dev, 0, 0, NULL, true); wcd_spi->spi = spi; spi_set_drvdata(spi, wcd_spi);