diff options
author | Thierry Reding <treding@nvidia.com> | 2014-11-12 13:39:05 +0100 |
---|---|---|
committer | James Thomas <james.thomas@codethink.co.uk> | 2015-04-14 10:42:54 +0100 |
commit | 017221b89fcf9d9fc8a208752c0829ef8a218022 (patch) | |
tree | 95d88610ee8b478e966263e6df4e410c365d08c7 | |
parent | b1b92655bae65b8c706c0d39ff647c292cd061ae (diff) | |
download | linux-017221b89fcf9d9fc8a208752c0829ef8a218022.tar.gz |
drm/ttm: dma: Fixes for 32-bit and 64-bit ARM
dma_alloc_coherent() returns a kernel virtual address that is part of
the linear range. Passing such an address to virt_to_page() is illegal
on non-coherent architectures. This causes the kernel to oops on 64-bit
ARM because the struct page * obtained from virt_to_page() points to
unmapped memory.
This commit fixes this by using phys_to_page() since we get a physical
address from dma_alloc_coherent(). Note that this is not a proper fix
because if an IOMMU is set up to translate addresses for the GPU this
address will be an I/O virtual address rather than a physical one. The
proper fix probably involves not getting a pointer to the struct page
in the first place, but that would be a much more intrusive change, if
at all possible.
Until that time, this temporary fix will allow TTM to work on 32-bit
and 64-bit ARM as well, provided that no IOMMU translations are enabled
for the GPU.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_page_alloc_dma.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 01e1d27eb078..e3c4a6bb2d9f 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -343,7 +343,11 @@ static struct dma_page *__ttm_dma_alloc_page(struct dma_pool *pool) &d_page->dma, pool->gfp_flags); if (d_page->vaddr) +#if defined(CONFIG_ARM) || defined(CONFIG_ARM64) + d_page->p = phys_to_page(d_page->dma); +#else d_page->p = virt_to_page(d_page->vaddr); +#endif else { kfree(d_page); d_page = NULL; |