mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-24 01:09:38 -05:00
drm/ttm: Add vmap/vunmap to TTM and TTM GEM helpers
The new functions ttm_bo_{vmap,vunmap}() map and unmap a TTM BO in kernel address space. The mapping's address is returned as struct dma_buf_map. Each function is a simplified version of TTM's existing kmap code. Both functions respect the memory's location ani/or writecombine flags. On top TTM's functions, GEM TTM helpers got drm_gem_ttm_{vmap,vunmap}(), two helpers that convert a GEM object into the TTM BO and forward the call to TTM's vmap/vunmap. These helpers can be dropped into the rsp GEM object callbacks. v5: * use size_t for storing mapping size (Christian) * ignore premapped memory areas correctly in ttm_bo_vunmap() * rebase onto latest TTM interfaces (Christian) * remove BUG() from ttm_bo_vmap() (Christian) v4: * drop ttm_kmap_obj_to_dma_buf() in favor of vmap helpers (Daniel, Christian) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Reviewed-by: Christian König <christian.koenig@amd.com> Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch> Tested-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20201103093015.1063-6-tzimmermann@suse.de
This commit is contained in:
parent
f216fcb8e4
commit
43676605f8
5 changed files with 163 additions and 0 deletions
|
@ -49,6 +49,43 @@ void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_gem_ttm_print_info);
|
EXPORT_SYMBOL(drm_gem_ttm_print_info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_gem_ttm_vmap() - vmap &ttm_buffer_object
|
||||||
|
* @gem: GEM object.
|
||||||
|
* @map: [out] returns the dma-buf mapping.
|
||||||
|
*
|
||||||
|
* Maps a GEM object with ttm_bo_vmap(). This function can be used as
|
||||||
|
* &drm_gem_object_funcs.vmap callback.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* 0 on success, or a negative errno code otherwise.
|
||||||
|
*/
|
||||||
|
int drm_gem_ttm_vmap(struct drm_gem_object *gem,
|
||||||
|
struct dma_buf_map *map)
|
||||||
|
{
|
||||||
|
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
|
||||||
|
|
||||||
|
return ttm_bo_vmap(bo, map);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_gem_ttm_vmap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* drm_gem_ttm_vunmap() - vunmap &ttm_buffer_object
|
||||||
|
* @gem: GEM object.
|
||||||
|
* @map: dma-buf mapping.
|
||||||
|
*
|
||||||
|
* Unmaps a GEM object with ttm_bo_vunmap(). This function can be used as
|
||||||
|
* &drm_gem_object_funcs.vmap callback.
|
||||||
|
*/
|
||||||
|
void drm_gem_ttm_vunmap(struct drm_gem_object *gem,
|
||||||
|
struct dma_buf_map *map)
|
||||||
|
{
|
||||||
|
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
|
||||||
|
|
||||||
|
ttm_bo_vunmap(bo, map);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(drm_gem_ttm_vunmap);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* drm_gem_ttm_mmap() - mmap &ttm_buffer_object
|
* drm_gem_ttm_mmap() - mmap &ttm_buffer_object
|
||||||
* @gem: GEM object.
|
* @gem: GEM object.
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <drm/ttm/ttm_bo_driver.h>
|
#include <drm/ttm/ttm_bo_driver.h>
|
||||||
#include <drm/ttm/ttm_placement.h>
|
#include <drm/ttm/ttm_placement.h>
|
||||||
#include <drm/drm_vma_manager.h>
|
#include <drm/drm_vma_manager.h>
|
||||||
|
#include <linux/dma-buf-map.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/highmem.h>
|
#include <linux/highmem.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
@ -471,6 +472,77 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ttm_bo_kunmap);
|
EXPORT_SYMBOL(ttm_bo_kunmap);
|
||||||
|
|
||||||
|
int ttm_bo_vmap(struct ttm_buffer_object *bo, struct dma_buf_map *map)
|
||||||
|
{
|
||||||
|
struct ttm_resource *mem = &bo->mem;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ttm_mem_io_reserve(bo->bdev, mem);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (mem->bus.is_iomem) {
|
||||||
|
void __iomem *vaddr_iomem;
|
||||||
|
size_t size = bo->num_pages << PAGE_SHIFT;
|
||||||
|
|
||||||
|
if (mem->bus.addr)
|
||||||
|
vaddr_iomem = (void __iomem *)mem->bus.addr;
|
||||||
|
else if (mem->bus.caching == ttm_write_combined)
|
||||||
|
vaddr_iomem = ioremap_wc(mem->bus.offset, size);
|
||||||
|
else
|
||||||
|
vaddr_iomem = ioremap(mem->bus.offset, size);
|
||||||
|
|
||||||
|
if (!vaddr_iomem)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_buf_map_set_vaddr_iomem(map, vaddr_iomem);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
struct ttm_operation_ctx ctx = {
|
||||||
|
.interruptible = false,
|
||||||
|
.no_wait_gpu = false
|
||||||
|
};
|
||||||
|
struct ttm_tt *ttm = bo->ttm;
|
||||||
|
pgprot_t prot;
|
||||||
|
void *vaddr;
|
||||||
|
|
||||||
|
ret = ttm_tt_populate(bo->bdev, ttm, &ctx);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to use vmap to get the desired page protection
|
||||||
|
* or to make the buffer object look contiguous.
|
||||||
|
*/
|
||||||
|
prot = ttm_io_prot(bo, mem, PAGE_KERNEL);
|
||||||
|
vaddr = vmap(ttm->pages, bo->num_pages, 0, prot);
|
||||||
|
if (!vaddr)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_buf_map_set_vaddr(map, vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ttm_bo_vmap);
|
||||||
|
|
||||||
|
void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct dma_buf_map *map)
|
||||||
|
{
|
||||||
|
struct ttm_resource *mem = &bo->mem;
|
||||||
|
|
||||||
|
if (dma_buf_map_is_null(map))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!map->is_iomem)
|
||||||
|
vunmap(map->vaddr);
|
||||||
|
else if (!mem->bus.addr)
|
||||||
|
iounmap(map->vaddr_iomem);
|
||||||
|
dma_buf_map_clear(map);
|
||||||
|
|
||||||
|
ttm_mem_io_free(bo->bdev, &bo->mem);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ttm_bo_vunmap);
|
||||||
|
|
||||||
static int ttm_bo_wait_free_node(struct ttm_buffer_object *bo,
|
static int ttm_bo_wait_free_node(struct ttm_buffer_object *bo,
|
||||||
bool dst_use_tt)
|
bool dst_use_tt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,11 +10,17 @@
|
||||||
#include <drm/ttm/ttm_bo_api.h>
|
#include <drm/ttm/ttm_bo_api.h>
|
||||||
#include <drm/ttm/ttm_bo_driver.h>
|
#include <drm/ttm/ttm_bo_driver.h>
|
||||||
|
|
||||||
|
struct dma_buf_map;
|
||||||
|
|
||||||
#define drm_gem_ttm_of_gem(gem_obj) \
|
#define drm_gem_ttm_of_gem(gem_obj) \
|
||||||
container_of(gem_obj, struct ttm_buffer_object, base)
|
container_of(gem_obj, struct ttm_buffer_object, base)
|
||||||
|
|
||||||
void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
|
void drm_gem_ttm_print_info(struct drm_printer *p, unsigned int indent,
|
||||||
const struct drm_gem_object *gem);
|
const struct drm_gem_object *gem);
|
||||||
|
int drm_gem_ttm_vmap(struct drm_gem_object *gem,
|
||||||
|
struct dma_buf_map *map);
|
||||||
|
void drm_gem_ttm_vunmap(struct drm_gem_object *gem,
|
||||||
|
struct dma_buf_map *map);
|
||||||
int drm_gem_ttm_mmap(struct drm_gem_object *gem,
|
int drm_gem_ttm_mmap(struct drm_gem_object *gem,
|
||||||
struct vm_area_struct *vma);
|
struct vm_area_struct *vma);
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ struct ttm_bo_global;
|
||||||
|
|
||||||
struct ttm_bo_device;
|
struct ttm_bo_device;
|
||||||
|
|
||||||
|
struct dma_buf_map;
|
||||||
|
|
||||||
struct drm_mm_node;
|
struct drm_mm_node;
|
||||||
|
|
||||||
struct ttm_placement;
|
struct ttm_placement;
|
||||||
|
@ -495,6 +497,32 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page,
|
||||||
*/
|
*/
|
||||||
void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map);
|
void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ttm_bo_vmap
|
||||||
|
*
|
||||||
|
* @bo: The buffer object.
|
||||||
|
* @map: pointer to a struct dma_buf_map representing the map.
|
||||||
|
*
|
||||||
|
* Sets up a kernel virtual mapping, using ioremap or vmap to the
|
||||||
|
* data in the buffer object. The parameter @map returns the virtual
|
||||||
|
* address as struct dma_buf_map. Unmap the buffer with ttm_bo_vunmap().
|
||||||
|
*
|
||||||
|
* Returns
|
||||||
|
* -ENOMEM: Out of memory.
|
||||||
|
* -EINVAL: Invalid range.
|
||||||
|
*/
|
||||||
|
int ttm_bo_vmap(struct ttm_buffer_object *bo, struct dma_buf_map *map);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ttm_bo_vunmap
|
||||||
|
*
|
||||||
|
* @bo: The buffer object.
|
||||||
|
* @map: Object describing the map to unmap.
|
||||||
|
*
|
||||||
|
* Unmaps a kernel map set up by ttm_bo_vmap().
|
||||||
|
*/
|
||||||
|
void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct dma_buf_map *map);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ttm_bo_mmap_obj - mmap memory backed by a ttm buffer object.
|
* ttm_bo_mmap_obj - mmap memory backed by a ttm buffer object.
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,6 +45,12 @@
|
||||||
*
|
*
|
||||||
* dma_buf_map_set_vaddr(&map. 0xdeadbeaf);
|
* dma_buf_map_set_vaddr(&map. 0xdeadbeaf);
|
||||||
*
|
*
|
||||||
|
* To set an address in I/O memory, use dma_buf_map_set_vaddr_iomem().
|
||||||
|
*
|
||||||
|
* .. code-block:: c
|
||||||
|
*
|
||||||
|
* dma_buf_map_set_vaddr_iomem(&map. 0xdeadbeaf);
|
||||||
|
*
|
||||||
* Test if a mapping is valid with either dma_buf_map_is_set() or
|
* Test if a mapping is valid with either dma_buf_map_is_set() or
|
||||||
* dma_buf_map_is_null().
|
* dma_buf_map_is_null().
|
||||||
*
|
*
|
||||||
|
@ -118,6 +124,20 @@ static inline void dma_buf_map_set_vaddr(struct dma_buf_map *map, void *vaddr)
|
||||||
map->is_iomem = false;
|
map->is_iomem = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dma_buf_map_set_vaddr_iomem - Sets a dma-buf mapping structure to an address in I/O memory
|
||||||
|
* @map: The dma-buf mapping structure
|
||||||
|
* @vaddr_iomem: An I/O-memory address
|
||||||
|
*
|
||||||
|
* Sets the address and the I/O-memory flag.
|
||||||
|
*/
|
||||||
|
static inline void dma_buf_map_set_vaddr_iomem(struct dma_buf_map *map,
|
||||||
|
void __iomem *vaddr_iomem)
|
||||||
|
{
|
||||||
|
map->vaddr_iomem = vaddr_iomem;
|
||||||
|
map->is_iomem = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dma_buf_map_is_equal - Compares two dma-buf mapping structures for equality
|
* dma_buf_map_is_equal - Compares two dma-buf mapping structures for equality
|
||||||
* @lhs: The dma-buf mapping structure
|
* @lhs: The dma-buf mapping structure
|
||||||
|
|
Loading…
Add table
Reference in a new issue