aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorHuang Shijie <shijie8@gmail.com>2013-12-18 10:41:00 -0500
committerBrian Norris <computersforpeace@gmail.com>2014-01-28 00:55:03 -0500
commit0ff76a920e3558307567b45aa0a91fb914924bfc (patch)
treede9fcf55103af0f753dda69599989c3b63758112 /drivers/mtd
parent06f216c83c25adadc231469d51ab133afdfe110a (diff)
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: Huang Shijie <shijie8@gmail.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/nand/gpmi-nand/gpmi-nand.c31
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index d1d13d86b7e0..ca6369fe91ff 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -367,25 +367,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr)
367 struct scatterlist *sgl = &this->data_sgl; 367 struct scatterlist *sgl = &this->data_sgl;
368 int ret; 368 int ret;
369 369
370 this->direct_dma_map_ok = true;
371
372 /* first try to map the upper buffer directly */ 370 /* first try to map the upper buffer directly */
373 sg_init_one(sgl, this->upper_buf, this->upper_len); 371 if (virt_addr_valid(this->upper_buf) &&
374 ret = dma_map_sg(this->dev, sgl, 1, dr); 372 !object_is_on_stack(this->upper_buf)) {
375 if (ret == 0) { 373 sg_init_one(sgl, this->upper_buf, this->upper_len);
376 /* We have to use our own DMA buffer. */
377 sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE);
378
379 if (dr == DMA_TO_DEVICE)
380 memcpy(this->data_buffer_dma, this->upper_buf,
381 this->upper_len);
382
383 ret = dma_map_sg(this->dev, sgl, 1, dr); 374 ret = dma_map_sg(this->dev, sgl, 1, dr);
384 if (ret == 0) 375 if (ret == 0)
385 dev_err(this->dev, "DMA mapping failed.\n"); 376 goto map_fail;
386 377
387 this->direct_dma_map_ok = false; 378 this->direct_dma_map_ok = true;
379 return;
388 } 380 }
381
382map_fail:
383 /* We have to use our own DMA buffer. */
384 sg_init_one(sgl, this->data_buffer_dma, this->upper_len);
385
386 if (dr == DMA_TO_DEVICE)
387 memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len);
388
389 dma_map_sg(this->dev, sgl, 1, dr);
390
391 this->direct_dma_map_ok = false;
389} 392}
390 393
391/* This will be called after the DMA operation is finished. */ 394/* This will be called after the DMA operation is finished. */