aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVignesh R <vigneshr@ti.com>2016-08-17 05:52:36 -0400
committerMark Brown <broonie@kernel.org>2016-08-17 07:24:01 -0400
commitb1b8153cf0aeeb7ae6d4f012b8beb2dcfc92c68a (patch)
treeb9fb07d7e31ff24bc7fb47138129548750d9612f
parent29b4817d4018df78086157ea3a55c1d9424a7cfc (diff)
spi: Add support to handle kmap'd buffers in spi_map_buf()
JFFS2 FS might sometime provide kmap'd buffers as destination buffers to read data from flash. Update spi_map_buf() function to generate sg_list for such buffers, so that SPI controllers drivers can use DMA to read data into such buffers. Signed-off-by: Vignesh R <vigneshr@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 51ad42fad567..2a5dd22efa34 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -37,6 +37,7 @@
37#include <linux/kthread.h> 37#include <linux/kthread.h>
38#include <linux/ioport.h> 38#include <linux/ioport.h>
39#include <linux/acpi.h> 39#include <linux/acpi.h>
40#include <linux/highmem.h>
40 41
41#define CREATE_TRACE_POINTS 42#define CREATE_TRACE_POINTS
42#include <trace/events/spi.h> 43#include <trace/events/spi.h>
@@ -709,6 +710,13 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
709{ 710{
710 const bool vmalloced_buf = is_vmalloc_addr(buf); 711 const bool vmalloced_buf = is_vmalloc_addr(buf);
711 unsigned int max_seg_size = dma_get_max_seg_size(dev); 712 unsigned int max_seg_size = dma_get_max_seg_size(dev);
713#ifdef CONFIG_HIGHMEM
714 const bool kmap_buf = ((unsigned long)buf >= PKMAP_BASE &&
715 (unsigned long)buf < (PKMAP_BASE +
716 (LAST_PKMAP * PAGE_SIZE)));
717#else
718 const bool kmap_buf = false;
719#endif
712 int desc_len; 720 int desc_len;
713 int sgs; 721 int sgs;
714 struct page *vm_page; 722 struct page *vm_page;
@@ -716,7 +724,7 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
716 size_t min; 724 size_t min;
717 int i, ret; 725 int i, ret;
718 726
719 if (vmalloced_buf) { 727 if (vmalloced_buf || kmap_buf) {
720 desc_len = min_t(int, max_seg_size, PAGE_SIZE); 728 desc_len = min_t(int, max_seg_size, PAGE_SIZE);
721 sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); 729 sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
722 } else if (virt_addr_valid(buf)) { 730 } else if (virt_addr_valid(buf)) {
@@ -732,10 +740,13 @@ static int spi_map_buf(struct spi_master *master, struct device *dev,
732 740
733 for (i = 0; i < sgs; i++) { 741 for (i = 0; i < sgs; i++) {
734 742
735 if (vmalloced_buf) { 743 if (vmalloced_buf || kmap_buf) {
736 min = min_t(size_t, 744 min = min_t(size_t,
737 len, desc_len - offset_in_page(buf)); 745 len, desc_len - offset_in_page(buf));
738 vm_page = vmalloc_to_page(buf); 746 if (vmalloced_buf)
747 vm_page = vmalloc_to_page(buf);
748 else
749 vm_page = kmap_to_page(buf);
739 if (!vm_page) { 750 if (!vm_page) {
740 sg_free_table(sgt); 751 sg_free_table(sgt);
741 return -ENOMEM; 752 return -ENOMEM;