diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-03-23 09:44:30 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-03-23 09:44:29 -0700 |
| commit | 2edff433a4933ca8037dab3e4983186ee7f01406 (patch) | |
| tree | 9a83a6b527a7c7e74146193f8b2e2c75ba1f656e | |
| parent | 3535fcdc1bf4d1ba37d125c56075c866e70e8599 (diff) | |
| parent | 554b0acd0ae605f63138c4e97d677566bbbe670e (diff) | |
Merge "ASoC: wcd-spi: pre-allocate buffers used for transfers"
| -rw-r--r-- | sound/soc/codecs/wcd-spi.c | 75 |
1 files changed, 50 insertions, 25 deletions
diff --git a/sound/soc/codecs/wcd-spi.c b/sound/soc/codecs/wcd-spi.c index b03a8a9caed7..3d2fe2c6bed9 100644 --- a/sound/soc/codecs/wcd-spi.c +++ b/sound/soc/codecs/wcd-spi.c @@ -81,8 +81,15 @@ #define WCD_SPI_WORD_BYTE_CNT (4) #define WCD_SPI_RW_MULTI_MIN_LEN (16) -/* Max size is closest multiple of 16 less than 64Kbytes */ -#define WCD_SPI_RW_MULTI_MAX_LEN ((64 * 1024) - 16) +/* Max size is 32 bytes less than 64Kbytes */ +#define WCD_SPI_RW_MULTI_MAX_LEN ((64 * 1024) - 32) + +/* + * Max size for the pre-allocated buffers is the max + * possible read/write length + 32 bytes for the SPI + * read/write command header itself. + */ +#define WCD_SPI_RW_MAX_BUF_SIZE (WCD_SPI_RW_MULTI_MAX_LEN + 32) /* Alignment requirements */ #define WCD_SPI_RW_MIN_ALIGN WCD_SPI_WORD_BYTE_CNT @@ -148,6 +155,10 @@ struct wcd_spi_priv { /* Completion object to indicate system resume completion */ struct completion resume_comp; + + /* Buffers to hold memory used for transfers */ + void *tx_buf; + void *rx_buf; }; enum xfer_request { @@ -229,17 +240,18 @@ static int wcd_spi_read_single(struct spi_device *spi, struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); struct spi_transfer *tx_xfer = &wcd_spi->xfer2[0]; struct spi_transfer *rx_xfer = &wcd_spi->xfer2[1]; - u8 *tx_buf; + u8 *tx_buf = wcd_spi->tx_buf; u32 frame = 0; int ret; dev_dbg(&spi->dev, "%s: remote_addr = 0x%x\n", __func__, remote_addr); - tx_buf = kzalloc(WCD_SPI_READ_SINGLE_LEN, - GFP_KERNEL | GFP_DMA); - if (!tx_buf) + if (!tx_buf) { + dev_err(&spi->dev, "%s: tx_buf not allocated\n", + __func__); return -ENOMEM; + } frame |= WCD_SPI_READ_FRAME_OPCODE; frame |= remote_addr & WCD_CMD_ADDR_MASK; @@ -255,7 +267,6 @@ static int wcd_spi_read_single(struct spi_device *spi, rx_xfer->len = sizeof(*val); ret = spi_sync(spi, &wcd_spi->msg2); - kfree(tx_buf); return ret; } @@ -266,8 +277,8 @@ static int wcd_spi_read_multi(struct spi_device *spi, { struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); struct spi_transfer *xfer = &wcd_spi->xfer1; - u8 *tx_buf; - u8 *rx_buf; + u8 *tx_buf = wcd_spi->tx_buf; + u8 *rx_buf = wcd_spi->rx_buf; u32 frame = 0; int ret; @@ -277,15 +288,9 @@ static int wcd_spi_read_multi(struct spi_device *spi, frame |= WCD_SPI_FREAD_FRAME_OPCODE; frame |= remote_addr & WCD_CMD_ADDR_MASK; - tx_buf = kzalloc(WCD_SPI_CMD_FREAD_LEN + len, - GFP_KERNEL | GFP_DMA); - if (!tx_buf) - return -ENOMEM; - - rx_buf = kzalloc(WCD_SPI_CMD_FREAD_LEN + len, - GFP_KERNEL | GFP_DMA); - if (!rx_buf) { - kfree(tx_buf); + if (!tx_buf || !rx_buf) { + dev_err(&spi->dev, "%s: %s not allocated\n", __func__, + (!tx_buf) ? "tx_buf" : "rx_buf"); return -ENOMEM; } @@ -305,8 +310,6 @@ static int wcd_spi_read_multi(struct spi_device *spi, memcpy(data, rx_buf + WCD_SPI_CMD_FREAD_LEN, len); done: - kfree(tx_buf); - kfree(rx_buf); return ret; } @@ -343,7 +346,7 @@ static int wcd_spi_write_multi(struct spi_device *spi, struct wcd_spi_priv *wcd_spi = spi_get_drvdata(spi); struct spi_transfer *xfer = &wcd_spi->xfer1; u32 frame = 0; - u8 *tx_buf; + u8 *tx_buf = wcd_spi->tx_buf; int xfer_len, ret; dev_dbg(&spi->dev, "%s: addr = 0x%x len = %zd\n", @@ -355,9 +358,11 @@ static int wcd_spi_write_multi(struct spi_device *spi, frame = cpu_to_be32(frame); xfer_len = len + sizeof(frame); - tx_buf = kzalloc(xfer_len, GFP_KERNEL); - if (!tx_buf) + if (!tx_buf) { + dev_err(&spi->dev, "%s: tx_buf not allocated\n", + __func__); return -ENOMEM; + } memcpy(tx_buf, &frame, sizeof(frame)); memcpy(tx_buf + sizeof(frame), data, len); @@ -371,8 +376,6 @@ static int wcd_spi_write_multi(struct spi_device *spi, dev_err(&spi->dev, "%s: Failed, addr = 0x%x, len = %zd\n", __func__, remote_addr, len); - kfree(tx_buf); - return ret; } @@ -1330,6 +1333,23 @@ static int wcd_spi_component_bind(struct device *dev, spi_message_init(&wcd_spi->msg2); spi_message_add_tail(&wcd_spi->xfer2[0], &wcd_spi->msg2); 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); + if (!wcd_spi->tx_buf) { + ret = -ENOMEM; + goto done; + } + + wcd_spi->rx_buf = kzalloc(WCD_SPI_RW_MAX_BUF_SIZE, + GFP_KERNEL | GFP_DMA); + if (!wcd_spi->rx_buf) { + kfree(wcd_spi->tx_buf); + wcd_spi->tx_buf = NULL; + ret = -ENOMEM; + goto done; + } done: return ret; } @@ -1347,6 +1367,11 @@ static void wcd_spi_component_unbind(struct device *dev, spi_transfer_del(&wcd_spi->xfer1); spi_transfer_del(&wcd_spi->xfer2[0]); spi_transfer_del(&wcd_spi->xfer2[1]); + + kfree(wcd_spi->tx_buf); + kfree(wcd_spi->rx_buf); + wcd_spi->tx_buf = NULL; + wcd_spi->rx_buf = NULL; } static const struct component_ops wcd_spi_component_ops = { |
