diff mbox

[1/2] spi: Fix mapping from vmalloc-ed buffer to scatter list

Message ID 1415979645-26264-1-git-send-email-ckeepax@opensource.wolfsonmicro.com (mailing list archive)
State Accepted
Commit c1aefbdd050e1fb15e92bcaf34d95b17ea952097
Headers show

Commit Message

Charles Keepax Nov. 14, 2014, 3:40 p.m. UTC
We can only use page_address on memory that has been mapped using kmap,
when the buffer passed to the SPI has been allocated by vmalloc the page
has not necessarily been mapped through kmap. This means sometimes
page_address will return NULL causing the pointer we pass to sg_set_buf
to be invalid.

As we only call page_address such that we can pass a virtual address to
sg_set_buf which will then immediately call virt_to_page on it, fix this
by calling sg_set_page directly rather then relying on the sg_set_buf
helper.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
 drivers/spi/spi.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

Comments

Mark Brown Nov. 14, 2014, 3:52 p.m. UTC | #1
On Fri, Nov 14, 2014 at 03:40:44PM +0000, Charles Keepax wrote:
> We can only use page_address on memory that has been mapped using kmap,
> when the buffer passed to the SPI has been allocated by vmalloc the page
> has not necessarily been mapped through kmap. This means sometimes
> page_address will return NULL causing the pointer we pass to sg_set_buf
> to be invalid.

Hrm, this is a bug in the mxs driver (which is where we copied the core
code from) - care to fix that too?

> As we only call page_address such that we can pass a virtual address to

s/such/so/
Charles Keepax Nov. 14, 2014, 4:06 p.m. UTC | #2
On Fri, Nov 14, 2014 at 03:52:22PM +0000, Mark Brown wrote:
> On Fri, Nov 14, 2014 at 03:40:44PM +0000, Charles Keepax wrote:
> > We can only use page_address on memory that has been mapped using kmap,
> > when the buffer passed to the SPI has been allocated by vmalloc the page
> > has not necessarily been mapped through kmap. This means sometimes
> > page_address will return NULL causing the pointer we pass to sg_set_buf
> > to be invalid.
> 
> Hrm, this is a bug in the mxs driver (which is where we copied the core
> code from) - care to fix that too?

Yeah no problem, won't be able to test it, but should be a fairly
trivial change and hopefully someone else can test.

> 
> > As we only call page_address such that we can pass a virtual address to
> 
> s/such/so/

Will ping a respin and include the mxs fixup too.

Thanks,
Charles


--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Charles Keepax Nov. 14, 2014, 5:11 p.m. UTC | #3
On Fri, Nov 14, 2014 at 04:06:07PM +0000, Charles Keepax wrote:
> On Fri, Nov 14, 2014 at 03:52:22PM +0000, Mark Brown wrote:
> > On Fri, Nov 14, 2014 at 03:40:44PM +0000, Charles Keepax wrote:
> > > We can only use page_address on memory that has been mapped using kmap,
> > > when the buffer passed to the SPI has been allocated by vmalloc the page
> > > has not necessarily been mapped through kmap. This means sometimes
> > > page_address will return NULL causing the pointer we pass to sg_set_buf
> > > to be invalid.
> > 
> > Hrm, this is a bug in the mxs driver (which is where we copied the core
> > code from) - care to fix that too?
> 
> Yeah no problem, won't be able to test it, but should be a fairly
> trivial change and hopefully someone else can test.

Ah... ok I think I see the difference here. The MXS architecture
has CONFIG_HIGHMEM=n whereas Arndale has CONFIG_HIGHMEM=y. So
that means on MXS all the pages will always be in low mem so I
think will always be mapped into the kernel logical address space
hence no problems. Not sure if it would be worth updating the
driver or not, what do you think?

Thanks,
Charles
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Nov. 14, 2014, 5:26 p.m. UTC | #4
On Fri, Nov 14, 2014 at 05:11:33PM +0000, Charles Keepax wrote:

> Ah... ok I think I see the difference here. The MXS architecture
> has CONFIG_HIGHMEM=n whereas Arndale has CONFIG_HIGHMEM=y. So
> that means on MXS all the pages will always be in low mem so I
> think will always be mapped into the kernel logical address space
> hence no problems. Not sure if it would be worth updating the
> driver or not, what do you think?

This is a user configurable option, it's not something that depends on
the architecture (and in any case it's better not to leave people
wondering why things are different when they consider consolidation).
Charles Keepax Nov. 14, 2014, 5:41 p.m. UTC | #5
On Fri, Nov 14, 2014 at 05:26:26PM +0000, Mark Brown wrote:
> On Fri, Nov 14, 2014 at 05:11:33PM +0000, Charles Keepax wrote:
> 
> > Ah... ok I think I see the difference here. The MXS architecture
> > has CONFIG_HIGHMEM=n whereas Arndale has CONFIG_HIGHMEM=y. So
> > that means on MXS all the pages will always be in low mem so I
> > think will always be mapped into the kernel logical address space
> > hence no problems. Not sure if it would be worth updating the
> > driver or not, what do you think?
> 
> This is a user configurable option, it's not something that depends on
> the architecture (and in any case it's better not to leave people
> wondering why things are different when they consider consolidation).

Cool, I will do the respin then.

Thanks,
Charles
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ebcb33d..50f20f2 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -615,13 +615,13 @@  static int spi_map_buf(struct spi_master *master, struct device *dev,
 				sg_free_table(sgt);
 				return -ENOMEM;
 			}
-			sg_buf = page_address(vm_page) +
-				((size_t)buf & ~PAGE_MASK);
+			sg_set_page(&sgt->sgl[i], vm_page,
+				    min, offset_in_page(buf));
 		} else {
 			sg_buf = buf;
+			sg_set_buf(&sgt->sgl[i], sg_buf, min);
 		}
 
-		sg_set_buf(&sgt->sgl[i], sg_buf, min);
 
 		buf += min;
 		len -= min;