[PATCH linux-next v2 2/2] spi: imx: don't manipulate trasnfer buffer directly

From: jiada_wang
Date: Tue May 23 2017 - 10:35:48 EST


From: Jiada Wang <jiada_wang@xxxxxxxxxx>

Previously spi_imx_u32_swap_u8() and spi_imx_u32_swap_u16() directly
manipulate const tx buffer by explicit cast from const void* to u32*,
this is not valid.

This patch by swap 32 bits data one by one before write to register,
and swap received 32 bits data one by one before save to receive
buffer to avoid direct manipulation of transfer buffer.

Signed-off-by: Jiada Wang <jiada_wang@xxxxxxxxxx>
Reported-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
drivers/spi/spi-imx.c | 83 +++++++++++++++++++++++----------------------------
1 file changed, 38 insertions(+), 45 deletions(-)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 2768e64..4144228 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -285,38 +285,38 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
#define MX51_ECSPI_TESTREG 0x20
#define MX51_ECSPI_TESTREG_LBC BIT(31)

-static void spi_imx_u32_swap_u8(struct spi_transfer *transfer, u32 *buf)
+static u32 spi_imx_u32_swap_u16(u32 val)
{
- int i;
+ u32 data = val;
+ u16 *temp = (u16 *)&data;

- if (!buf)
- return;
+ *temp = cpu_to_be16(*temp);
+ *(temp + 1) = cpu_to_be16(*(temp + 1));

- for (i = 0; i < transfer->len / 4; i++)
- *(buf + i) = cpu_to_be32(*(buf + i));
+ data = cpu_to_be32(data);
+
+ return data;
}

-static void spi_imx_u32_swap_u16(struct spi_transfer *transfer, u32 *buf)
+static void spi_imx_buf_rx_swap_u32(struct spi_imx_data *spi_imx)
{
- int i;
-
- if (!buf)
- return;
-
- for (i = 0; i < transfer->len / 4; i++) {
- u16 *temp = (u16 *)buf;
+ unsigned int val = readl(spi_imx->base + MXC_CSPIRXDATA);

- *(temp + i * 2) = cpu_to_be16(*(temp + i * 2));
- *(temp + i * 2 + 1) = cpu_to_be16(*(temp + i * 2 + 1));
+ if (spi_imx->rx_buf) {
+ if (spi_imx->bpw_w == 1)
+ val = cpu_to_be32(val);
+ else if (spi_imx->bpw_w == 2)
+ val = spi_imx_u32_swap_u16(val);

- *(buf + i) = cpu_to_be32(*(buf + i));
+ *(u32 *)spi_imx->rx_buf = val;
+ spi_imx->rx_buf += sizeof(u32);
}
}

static void spi_imx_buf_rx_swap(struct spi_imx_data *spi_imx)
{
if (!spi_imx->bpw_rx) {
- spi_imx_buf_rx_u32(spi_imx);
+ spi_imx_buf_rx_swap_u32(spi_imx);
return;
}

@@ -326,6 +326,24 @@ static void spi_imx_buf_rx_swap(struct spi_imx_data *spi_imx)
spi_imx_buf_rx_u16(spi_imx);
}

+static void spi_imx_buf_tx_swap_u32(struct spi_imx_data *spi_imx)
+{
+ u32 val = 0;
+
+ if (spi_imx->tx_buf) {
+ val = *(u32 *)spi_imx->tx_buf;
+ spi_imx->tx_buf += sizeof(u32);
+ }
+
+ spi_imx->count -= sizeof(u32);
+ if (spi_imx->bpw_w == 1)
+ val = cpu_to_be32(val);
+ else if (spi_imx->bpw_w == 2)
+ val = spi_imx_u32_swap_u16(val);
+
+ writel(val, spi_imx->base + MXC_CSPITXDATA);
+}
+
static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
{
u32 ctrl, val;
@@ -346,7 +364,7 @@ static void spi_imx_buf_tx_swap(struct spi_imx_data *spi_imx)
}

if (spi_imx->count >= sizeof(u32)) {
- spi_imx_buf_tx_u32(spi_imx);
+ spi_imx_buf_tx_swap_u32(spi_imx);
return;
}

@@ -1212,18 +1230,6 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
else
spi_imx->count_index = spi_imx->count % sizeof(u32);

- switch (spi_imx->bpw_w) {
- case 1:
- spi_imx_u32_swap_u8(transfer,
- (u32 *)transfer->tx_buf);
- break;
- case 2:
- spi_imx_u32_swap_u16(transfer,
- (u32 *)transfer->tx_buf);
- break;
- default:
- break;
- }
}

reinit_completion(&spi_imx->xfer_done);
@@ -1242,21 +1248,8 @@ static int spi_imx_pio_transfer(struct spi_device *spi,
return -ETIMEDOUT;
}

- if (spi_imx->dynamic_burst) {
- switch (spi_imx->bpw_w) {
- case 1:
- spi_imx_u32_swap_u8(transfer,
- (u32 *)transfer->rx_buf);
- break;
- case 2:
- spi_imx_u32_swap_u16(transfer,
- (u32 *)transfer->rx_buf);
- break;
- default:
- break;
- }
+ if (spi_imx->dynamic_burst)
spi_imx->dynamic_burst = 0;
- }

return transfer->len;
}
--
2.7.4