Commit 38058322 authored by Boris Brezillon's avatar Boris Brezillon Committed by Mark Brown

spi: spi-mem: Add extra sanity checks on the op param

Some combinations are simply not valid and should be rejected before
the op is passed to the SPI controller driver.

Add an spi_mem_check_op() helper and use it in spi_mem_exec_op() and
spi_mem_supports_op() to make sure the spi-mem operation is valid.
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent f34ecdbd
......@@ -12,6 +12,8 @@
#include "internals.h"
#define SPI_MEM_MAX_BUSWIDTH 4
/**
* spi_controller_dma_map_mem_op_data() - DMA-map the buffer attached to a
* memory operation
......@@ -149,6 +151,44 @@ static bool spi_mem_default_supports_op(struct spi_mem *mem,
}
EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
static bool spi_mem_buswidth_is_valid(u8 buswidth)
{
if (hweight8(buswidth) > 1 || buswidth > SPI_MEM_MAX_BUSWIDTH)
return false;
return true;
}
static int spi_mem_check_op(const struct spi_mem_op *op)
{
if (!op->cmd.buswidth)
return -EINVAL;
if ((op->addr.nbytes && !op->addr.buswidth) ||
(op->dummy.nbytes && !op->dummy.buswidth) ||
(op->data.nbytes && !op->data.buswidth))
return -EINVAL;
if (spi_mem_buswidth_is_valid(op->cmd.buswidth) ||
spi_mem_buswidth_is_valid(op->addr.buswidth) ||
spi_mem_buswidth_is_valid(op->dummy.buswidth) ||
spi_mem_buswidth_is_valid(op->data.buswidth))
return -EINVAL;
return 0;
}
static bool spi_mem_internal_supports_op(struct spi_mem *mem,
const struct spi_mem_op *op)
{
struct spi_controller *ctlr = mem->spi->controller;
if (ctlr->mem_ops && ctlr->mem_ops->supports_op)
return ctlr->mem_ops->supports_op(mem, op);
return spi_mem_default_supports_op(mem, op);
}
/**
* spi_mem_supports_op() - Check if a memory device and the controller it is
* connected to support a specific memory operation
......@@ -166,12 +206,10 @@ EXPORT_SYMBOL_GPL(spi_mem_default_supports_op);
*/
bool spi_mem_supports_op(struct spi_mem *mem, const struct spi_mem_op *op)
{
struct spi_controller *ctlr = mem->spi->controller;
if (ctlr->mem_ops && ctlr->mem_ops->supports_op)
return ctlr->mem_ops->supports_op(mem, op);
if (spi_mem_check_op(op))
return false;
return spi_mem_default_supports_op(mem, op);
return spi_mem_internal_supports_op(mem, op);
}
EXPORT_SYMBOL_GPL(spi_mem_supports_op);
......@@ -196,7 +234,11 @@ int spi_mem_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
u8 *tmpbuf;
int ret;
if (!spi_mem_supports_op(mem, op))
ret = spi_mem_check_op(op);
if (ret)
return ret;
if (!spi_mem_internal_supports_op(mem, op))
return -ENOTSUPP;
if (ctlr->mem_ops) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment