Commit 0ff76a92 authored by Huang Shijie's avatar Huang Shijie Committed by Brian Norris

mtd: gpmi: add sanity check when mapping DMA for read_buf/write_buf

The buffer pointer passed from the upper layer may points to
a buffer in the stack or a buffer allocated by vmalloc, and etc..

This patch adds more sanity check to this buffer.
After this patch, if we meet a buffer which is allocated by vmalloc or
a buffer in the stack, we will use our own DMA buffer @data_buffer_dma
to do the DMA operations. If the buffer is not the cases above, we will
map it for DMA operations directly.
Signed-off-by: default avatarHuang Shijie <shijie8@gmail.com>
Signed-off-by: default avatarBrian Norris <computersforpeace@gmail.com>
parent 06f216c8
...@@ -367,25 +367,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr) ...@@ -367,25 +367,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
struct scatterlist *sgl = &this->data_sgl; struct scatterlist *sgl = &this->data_sgl;
int ret; int ret;
this->direct_dma_map_ok = true;
/* first try to map the upper buffer directly */ /* first try to map the upper buffer directly */
sg_init_one(sgl, this->upper_buf, this->upper_len); if (virt_addr_valid(this->upper_buf) &&
ret = dma_map_sg(this->dev, sgl, 1, dr); !object_is_on_stack(this->upper_buf)) {
if (ret == 0) { sg_init_one(sgl, this->upper_buf, this->upper_len);
/* We have to use our own DMA buffer. */
sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
if (dr == DMA_TO_DEVICE)
memcpy(this->data_buffer_dma, this->upper_buf,
this->upper_len);
ret = dma_map_sg(this->dev, sgl, 1, dr); ret = dma_map_sg(this->dev, sgl, 1, dr);
if (ret == 0) if (ret == 0)
dev_err(this->dev, "DMA mapping failed.\n"); goto map_fail;
this->direct_dma_map_ok = false; this->direct_dma_map_ok = true;
return;
} }
map_fail:
/* We have to use our own DMA buffer. */
sg_init_one(sgl, this->data_buffer_dma, this->upper_len);
if (dr == DMA_TO_DEVICE)
memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len);
dma_map_sg(this->dev, sgl, 1, dr);
this->direct_dma_map_ok = false;
} }
/* This will be called after the DMA operation is finished. */ /* This will be called after the DMA operation is finished. */
......
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