Commit 6b5ce4a1 authored by Thomas Zimmermann's avatar Thomas Zimmermann

drm/vram: Move VRAM memory manager to GEM VRAM implementation

The separation between GEM VRAM objects and the memory manager is
artificial, as they are only used with each other. Copying both
implementations into the same file is a first step to simplifying
the code.

This patch only moves code without functional changes.

v3:
	* update to use dev->vma_offset_manager
v2:
	* update for debugfs support
	* typos in commit message
Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarGerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190911110910.30698-2-tzimmermann@suse.de
parent e1218b8c
...@@ -400,18 +400,6 @@ GEM VRAM Helper Functions Reference ...@@ -400,18 +400,6 @@ GEM VRAM Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c .. kernel-doc:: drivers/gpu/drm/drm_gem_vram_helper.c
:export: :export:
VRAM MM Helper Functions Reference
----------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
:doc: overview
.. kernel-doc:: include/drm/drm_vram_mm_helper.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_vram_mm_helper.c
:export:
GEM TTM Helper Functions Reference GEM TTM Helper Functions Reference
----------------------------------- -----------------------------------
......
...@@ -33,8 +33,7 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o ...@@ -33,8 +33,7 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
drm_vram_helper-y := drm_gem_vram_helper.o \ drm_vram_helper-y := drm_gem_vram_helper.o \
drm_vram_helper_common.o \ drm_vram_helper_common.o
drm_vram_mm_helper.o
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
drm_ttm_helper-y := drm_gem_ttm_helper.o drm_ttm_helper-y := drm_gem_ttm_helper.o
......
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_pci.h> #include <drm/drm_pci.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include "ast_drv.h" #include "ast_drv.h"
......
...@@ -33,7 +33,6 @@ ...@@ -33,7 +33,6 @@
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include "ast_drv.h" #include "ast_drv.h"
......
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include "ast_drv.h" #include "ast_drv.h"
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_simple_kms_helper.h> #include <drm/drm_simple_kms_helper.h>
#include <drm/drm_vram_mm_helper.h>
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
......
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <drm/drm_debugfs.h>
#include <drm/drm_device.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_ttm_helper.h> #include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_mode.h> #include <drm/drm_mode.h>
#include <drm/drm_prime.h> #include <drm/drm_prime.h>
#include <drm/drm_vram_mm_helper.h> #include <drm/drm_vram_mm_helper.h>
...@@ -15,6 +17,11 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; ...@@ -15,6 +17,11 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
* *
* This library provides a GEM buffer object that is backed by video RAM * This library provides a GEM buffer object that is backed by video RAM
* (VRAM). It can be used for framebuffer devices with dedicated memory. * (VRAM). It can be used for framebuffer devices with dedicated memory.
*
* The data structure &struct drm_vram_mm and its helpers implement a memory
* manager for simple framebuffer devices with dedicated video memory. Buffer
* objects are either placed in video RAM or evicted to system memory. The rsp.
* buffer object is provided by &struct drm_gem_vram_object.
*/ */
/* /*
...@@ -736,3 +743,343 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { ...@@ -736,3 +743,343 @@ static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = {
.vunmap = drm_gem_vram_object_vunmap, .vunmap = drm_gem_vram_object_vunmap,
.print_info = drm_gem_ttm_print_info, .print_info = drm_gem_ttm_print_info,
}; };
/*
* VRAM memory manager
*/
/*
* TTM TT
*/
static void backend_func_destroy(struct ttm_tt *tt)
{
ttm_tt_fini(tt);
kfree(tt);
}
static struct ttm_backend_func backend_func = {
.destroy = backend_func_destroy
};
/*
* TTM BO device
*/
static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
struct ttm_tt *tt;
int ret;
tt = kzalloc(sizeof(*tt), GFP_KERNEL);
if (!tt)
return NULL;
tt->func = &backend_func;
ret = ttm_tt_init(tt, bo, page_flags);
if (ret < 0)
goto err_ttm_tt_init;
return tt;
err_ttm_tt_init:
kfree(tt);
return NULL;
}
static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man)
{
switch (type) {
case TTM_PL_SYSTEM:
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
break;
case TTM_PL_VRAM:
man->func = &ttm_bo_manager_func;
man->flags = TTM_MEMTYPE_FLAG_FIXED |
TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_WC;
man->default_caching = TTM_PL_FLAG_WC;
break;
default:
return -EINVAL;
}
return 0;
}
static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
struct ttm_placement *placement)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (vmm->funcs && vmm->funcs->evict_flags)
vmm->funcs->evict_flags(bo, placement);
}
static int bo_driver_verify_access(struct ttm_buffer_object *bo,
struct file *filp)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (!vmm->funcs || !vmm->funcs->verify_access)
return 0;
return vmm->funcs->verify_access(bo, filp);
}
static void bo_driver_move_notify(struct ttm_buffer_object *bo,
bool evict,
struct ttm_mem_reg *new_mem)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (!vmm->funcs || !vmm->funcs->move_notify)
return;
vmm->funcs->move_notify(bo, evict, new_mem);
}
static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
struct ttm_mem_reg *mem)
{
struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
return -EINVAL;
mem->bus.addr = NULL;
mem->bus.size = mem->num_pages << PAGE_SHIFT;
switch (mem->mem_type) {
case TTM_PL_SYSTEM: /* nothing to do */
mem->bus.offset = 0;
mem->bus.base = 0;
mem->bus.is_iomem = false;
break;
case TTM_PL_VRAM:
mem->bus.offset = mem->start << PAGE_SHIFT;
mem->bus.base = vmm->vram_base;
mem->bus.is_iomem = true;
break;
default:
return -EINVAL;
}
return 0;
}
static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
struct ttm_mem_reg *mem)
{ }
static struct ttm_bo_driver bo_driver = {
.ttm_tt_create = bo_driver_ttm_tt_create,
.ttm_tt_populate = ttm_pool_populate,
.ttm_tt_unpopulate = ttm_pool_unpopulate,
.init_mem_type = bo_driver_init_mem_type,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = bo_driver_evict_flags,
.verify_access = bo_driver_verify_access,
.move_notify = bo_driver_move_notify,
.io_mem_reserve = bo_driver_io_mem_reserve,
.io_mem_free = bo_driver_io_mem_free,
};
/*
* struct drm_vram_mm
*/
#if defined(CONFIG_DEBUG_FS)
static int drm_vram_mm_debugfs(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_vram_mm *vmm = node->minor->dev->vram_mm;
struct drm_mm *mm = vmm->bdev.man[TTM_PL_VRAM].priv;
struct ttm_bo_global *glob = vmm->bdev.glob;
struct drm_printer p = drm_seq_file_printer(m);
spin_lock(&glob->lru_lock);
drm_mm_print(mm, &p);
spin_unlock(&glob->lru_lock);
return 0;
}
static const struct drm_info_list drm_vram_mm_debugfs_list[] = {
{ "vram-mm", drm_vram_mm_debugfs, 0, NULL },
};
#endif
/**
* drm_vram_mm_debugfs_init() - Register VRAM MM debugfs file.
*
* @minor: drm minor device.
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_debugfs_init(struct drm_minor *minor)
{
int ret = 0;
#if defined(CONFIG_DEBUG_FS)
ret = drm_debugfs_create_files(drm_vram_mm_debugfs_list,
ARRAY_SIZE(drm_vram_mm_debugfs_list),
minor->debugfs_root, minor);
#endif
return ret;
}
EXPORT_SYMBOL(drm_vram_mm_debugfs_init);
/**
* drm_vram_mm_init() - Initialize an instance of VRAM MM.
* @vmm: the VRAM MM instance to initialize
* @dev: the DRM device
* @vram_base: the base address of the video memory
* @vram_size: the size of the video memory in bytes
* @funcs: callback functions for buffer objects
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs)
{
int ret;
vmm->vram_base = vram_base;
vmm->vram_size = vram_size;
vmm->funcs = funcs;
ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
dev->anon_inode->i_mapping,
dev->vma_offset_manager,
true);
if (ret)
return ret;
ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
if (ret)
return ret;
return 0;
}
EXPORT_SYMBOL(drm_vram_mm_init);
/**
* drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM.
* @vmm: the VRAM MM instance to clean up
*/
void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
{
ttm_bo_device_release(&vmm->bdev);
}
EXPORT_SYMBOL(drm_vram_mm_cleanup);
/**
* drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap()
* @filp: the mapping's file structure
* @vma: the mapping's memory area
* @vmm: the VRAM MM instance
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
struct drm_vram_mm *vmm)
{
return ttm_bo_mmap(filp, vma, &vmm->bdev);
}
EXPORT_SYMBOL(drm_vram_mm_mmap);
/*
* Helpers for integration with struct drm_device
*/
/**
* drm_vram_helper_alloc_mm - Allocates a device's instance of \
&struct drm_vram_mm
* @dev: the DRM device
* @vram_base: the base address of the video memory
* @vram_size: the size of the video memory in bytes
* @funcs: callback functions for buffer objects
*
* Returns:
* The new instance of &struct drm_vram_mm on success, or
* an ERR_PTR()-encoded errno code otherwise.
*/
struct drm_vram_mm *drm_vram_helper_alloc_mm(
struct drm_device *dev, uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs)
{
int ret;
if (WARN_ON(dev->vram_mm))
return dev->vram_mm;
dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
if (!dev->vram_mm)
return ERR_PTR(-ENOMEM);
ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs);
if (ret)
goto err_kfree;
return dev->vram_mm;
err_kfree:
kfree(dev->vram_mm);
dev->vram_mm = NULL;
return ERR_PTR(ret);
}
EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
/**
* drm_vram_helper_release_mm - Releases a device's instance of \
&struct drm_vram_mm
* @dev: the DRM device
*/
void drm_vram_helper_release_mm(struct drm_device *dev)
{
if (!dev->vram_mm)
return;
drm_vram_mm_cleanup(dev->vram_mm);
kfree(dev->vram_mm);
dev->vram_mm = NULL;
}
EXPORT_SYMBOL(drm_vram_helper_release_mm);
/*
* Helpers for &struct file_operations
*/
/**
* drm_vram_mm_file_operations_mmap() - \
Implements &struct file_operations.mmap()
* @filp: the mapping's file structure
* @vma: the mapping's memory area
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_file_operations_mmap(
struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
return -EINVAL;
return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
}
EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);
// SPDX-License-Identifier: GPL-2.0-or-later
#include <drm/drm_debugfs.h>
#include <drm/drm_device.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include <drm/ttm/ttm_page_alloc.h>
/**
* DOC: overview
*
* The data structure &struct drm_vram_mm and its helpers implement a memory
* manager for simple framebuffer devices with dedicated video memory. Buffer
* objects are either placed in video RAM or evicted to system memory. These
* helper functions work well with &struct drm_gem_vram_object.
*/
/*
* TTM TT
*/
static void backend_func_destroy(struct ttm_tt *tt)
{
ttm_tt_fini(tt);
kfree(tt);
}
static struct ttm_backend_func backend_func = {
.destroy = backend_func_destroy
};
/*
* TTM BO device
*/
static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
uint32_t page_flags)
{
struct ttm_tt *tt;
int ret;
tt = kzalloc(sizeof(*tt), GFP_KERNEL);
if (!tt)
return NULL;
tt->func = &backend_func;
ret = ttm_tt_init(tt, bo, page_flags);
if (ret < 0)
goto err_ttm_tt_init;
return tt;
err_ttm_tt_init:
kfree(tt);
return NULL;
}
static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
struct ttm_mem_type_manager *man)
{
switch (type) {
case TTM_PL_SYSTEM:
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
break;
case TTM_PL_VRAM:
man->func = &ttm_bo_manager_func;
man->flags = TTM_MEMTYPE_FLAG_FIXED |
TTM_MEMTYPE_FLAG_MAPPABLE;
man->available_caching = TTM_PL_FLAG_UNCACHED |
TTM_PL_FLAG_WC;
man->default_caching = TTM_PL_FLAG_WC;
break;
default:
return -EINVAL;
}
return 0;
}
static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
struct ttm_placement *placement)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (vmm->funcs && vmm->funcs->evict_flags)
vmm->funcs->evict_flags(bo, placement);
}
static int bo_driver_verify_access(struct ttm_buffer_object *bo,
struct file *filp)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (!vmm->funcs || !vmm->funcs->verify_access)
return 0;
return vmm->funcs->verify_access(bo, filp);
}
static void bo_driver_move_notify(struct ttm_buffer_object *bo,
bool evict,
struct ttm_mem_reg *new_mem)
{
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
if (!vmm->funcs || !vmm->funcs->move_notify)
return;
vmm->funcs->move_notify(bo, evict, new_mem);
}
static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
struct ttm_mem_reg *mem)
{
struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
return -EINVAL;
mem->bus.addr = NULL;
mem->bus.size = mem->num_pages << PAGE_SHIFT;
switch (mem->mem_type) {
case TTM_PL_SYSTEM: /* nothing to do */
mem->bus.offset = 0;
mem->bus.base = 0;
mem->bus.is_iomem = false;
break;
case TTM_PL_VRAM:
mem->bus.offset = mem->start << PAGE_SHIFT;
mem->bus.base = vmm->vram_base;
mem->bus.is_iomem = true;
break;
default:
return -EINVAL;
}
return 0;
}
static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
struct ttm_mem_reg *mem)
{ }
static struct ttm_bo_driver bo_driver = {
.ttm_tt_create = bo_driver_ttm_tt_create,
.ttm_tt_populate = ttm_pool_populate,
.ttm_tt_unpopulate = ttm_pool_unpopulate,
.init_mem_type = bo_driver_init_mem_type,
.eviction_valuable = ttm_bo_eviction_valuable,
.evict_flags = bo_driver_evict_flags,
.verify_access = bo_driver_verify_access,
.move_notify = bo_driver_move_notify,
.io_mem_reserve = bo_driver_io_mem_reserve,
.io_mem_free = bo_driver_io_mem_free,
};
/*
* struct drm_vram_mm
*/
#if defined(CONFIG_DEBUG_FS)
static int drm_vram_mm_debugfs(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_vram_mm *vmm = node->minor->dev->vram_mm;
struct drm_mm *mm = vmm->bdev.man[TTM_PL_VRAM].priv;
struct ttm_bo_global *glob = vmm->bdev.glob;
struct drm_printer p = drm_seq_file_printer(m);
spin_lock(&glob->lru_lock);
drm_mm_print(mm, &p);
spin_unlock(&glob->lru_lock);
return 0;
}
static const struct drm_info_list drm_vram_mm_debugfs_list[] = {
{ "vram-mm", drm_vram_mm_debugfs, 0, NULL },
};
#endif
/**
* drm_vram_mm_debugfs_init() - Register VRAM MM debugfs file.
*
* @minor: drm minor device.
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_debugfs_init(struct drm_minor *minor)
{
int ret = 0;
#if defined(CONFIG_DEBUG_FS)
ret = drm_debugfs_create_files(drm_vram_mm_debugfs_list,
ARRAY_SIZE(drm_vram_mm_debugfs_list),
minor->debugfs_root, minor);
#endif
return ret;
}
EXPORT_SYMBOL(drm_vram_mm_debugfs_init);
/**
* drm_vram_mm_init() - Initialize an instance of VRAM MM.
* @vmm: the VRAM MM instance to initialize
* @dev: the DRM device
* @vram_base: the base address of the video memory
* @vram_size: the size of the video memory in bytes
* @funcs: callback functions for buffer objects
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs)
{
int ret;
vmm->vram_base = vram_base;
vmm->vram_size = vram_size;
vmm->funcs = funcs;
ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
dev->anon_inode->i_mapping,
dev->vma_offset_manager,
true);
if (ret)
return ret;
ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
if (ret)
return ret;
return 0;
}
EXPORT_SYMBOL(drm_vram_mm_init);
/**
* drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM.
* @vmm: the VRAM MM instance to clean up
*/
void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
{
ttm_bo_device_release(&vmm->bdev);
}
EXPORT_SYMBOL(drm_vram_mm_cleanup);
/**
* drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap()
* @filp: the mapping's file structure
* @vma: the mapping's memory area
* @vmm: the VRAM MM instance
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
struct drm_vram_mm *vmm)
{
return ttm_bo_mmap(filp, vma, &vmm->bdev);
}
EXPORT_SYMBOL(drm_vram_mm_mmap);
/*
* Helpers for integration with struct drm_device
*/
/**
* drm_vram_helper_alloc_mm - Allocates a device's instance of \
&struct drm_vram_mm
* @dev: the DRM device
* @vram_base: the base address of the video memory
* @vram_size: the size of the video memory in bytes
* @funcs: callback functions for buffer objects
*
* Returns:
* The new instance of &struct drm_vram_mm on success, or
* an ERR_PTR()-encoded errno code otherwise.
*/
struct drm_vram_mm *drm_vram_helper_alloc_mm(
struct drm_device *dev, uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs)
{
int ret;
if (WARN_ON(dev->vram_mm))
return dev->vram_mm;
dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
if (!dev->vram_mm)
return ERR_PTR(-ENOMEM);
ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs);
if (ret)
goto err_kfree;
return dev->vram_mm;
err_kfree:
kfree(dev->vram_mm);
dev->vram_mm = NULL;
return ERR_PTR(ret);
}
EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
/**
* drm_vram_helper_release_mm - Releases a device's instance of \
&struct drm_vram_mm
* @dev: the DRM device
*/
void drm_vram_helper_release_mm(struct drm_device *dev)
{
if (!dev->vram_mm)
return;
drm_vram_mm_cleanup(dev->vram_mm);
kfree(dev->vram_mm);
dev->vram_mm = NULL;
}
EXPORT_SYMBOL(drm_vram_helper_release_mm);
/*
* Helpers for &struct file_operations
*/
/**
* drm_vram_mm_file_operations_mmap() - \
Implements &struct file_operations.mmap()
* @filp: the mapping's file structure
* @vma: the mapping's memory area
*
* Returns:
* 0 on success, or
* a negative error code otherwise.
*/
int drm_vram_mm_file_operations_mmap(
struct file *filp, struct vm_area_struct *vma)
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
return -EINVAL;
return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
}
EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_probe_helper.h> #include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h> #include <drm/drm_vblank.h>
#include <drm/drm_vram_mm_helper.h>
#include "hibmc_drm_drv.h" #include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h" #include "hibmc_drm_regs.h"
......
...@@ -17,7 +17,6 @@ ...@@ -17,7 +17,6 @@
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_print.h> #include <drm/drm_print.h>
#include <drm/drm_vram_mm_helper.h>
#include "hibmc_drm_drv.h" #include "hibmc_drm_drv.h"
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <drm/drm_fb_helper.h> #include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include "mgag200_reg.h" #include "mgag200_reg.h"
......
...@@ -20,8 +20,6 @@ ...@@ -20,8 +20,6 @@
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_gem_vram_helper.h> #include <drm/drm_gem_vram_helper.h>
#include <drm/drm_vram_mm_helper.h>
#include "vboxvideo_guest.h" #include "vboxvideo_guest.h"
#include "vboxvideo_vbe.h" #include "vboxvideo_vbe.h"
#include "hgsmi_ch_setup.h" #include "hgsmi_ch_setup.h"
......
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
#ifndef DRM_GEM_VRAM_HELPER_H #ifndef DRM_GEM_VRAM_HELPER_H
#define DRM_GEM_VRAM_HELPER_H #define DRM_GEM_VRAM_HELPER_H
#include <drm/drm_file.h>
#include <drm/drm_gem.h> #include <drm/drm_gem.h>
#include <drm/drm_ioctl.h>
#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_placement.h> #include <drm/ttm/ttm_placement.h>
#include <linux/kernel.h> /* for container_of() */ #include <linux/kernel.h> /* for container_of() */
struct drm_mode_create_dumb; struct drm_mode_create_dumb;
...@@ -145,4 +149,86 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, ...@@ -145,4 +149,86 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
.dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, \ .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, \
.gem_prime_mmap = drm_gem_prime_mmap .gem_prime_mmap = drm_gem_prime_mmap
/*
* VRAM memory manager
*/
/**
* struct drm_vram_mm - An instance of VRAM MM
* @vram_base: Base address of the managed video memory
* @vram_size: Size of the managed video memory in bytes
* @bdev: The TTM BO device.
* @funcs: TTM BO functions
*
* The fields &struct drm_vram_mm.vram_base and
* &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
* available for public read access. Use the field
* &struct drm_vram_mm.bdev to access the TTM BO device.
*/
struct drm_vram_mm {
uint64_t vram_base;
size_t vram_size;
struct ttm_bo_device bdev;
const struct drm_vram_mm_funcs *funcs;
};
/**
* drm_vram_mm_of_bdev() - \
Returns the container of type &struct ttm_bo_device for field bdev.
* @bdev: the TTM BO device
*
* Returns:
* The containing instance of &struct drm_vram_mm
*/
static inline struct drm_vram_mm *drm_vram_mm_of_bdev(
struct ttm_bo_device *bdev)
{
return container_of(bdev, struct drm_vram_mm, bdev);
}
int drm_vram_mm_debugfs_init(struct drm_minor *minor);
int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs);
void drm_vram_mm_cleanup(struct drm_vram_mm *vmm);
int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
struct drm_vram_mm *vmm);
/*
* Helpers for integration with struct drm_device
*/
struct drm_vram_mm *drm_vram_helper_alloc_mm(
struct drm_device *dev, uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs);
void drm_vram_helper_release_mm(struct drm_device *dev);
/*
* Helpers for &struct file_operations
*/
int drm_vram_mm_file_operations_mmap(
struct file *filp, struct vm_area_struct *vma);
/**
* define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \
&struct file_operations
*
* Drivers that use VRAM MM can use this macro to initialize
* &struct file_operations with default functions.
*/
#define DRM_VRAM_MM_FILE_OPERATIONS \
.llseek = no_llseek, \
.read = drm_read, \
.poll = drm_poll, \
.unlocked_ioctl = drm_ioctl, \
.compat_ioctl = drm_compat_ioctl, \
.mmap = drm_vram_mm_file_operations_mmap, \
.open = drm_open, \
.release = drm_release \
#endif #endif
...@@ -29,81 +29,4 @@ struct drm_vram_mm_funcs { ...@@ -29,81 +29,4 @@ struct drm_vram_mm_funcs {
struct ttm_mem_reg *new_mem); struct ttm_mem_reg *new_mem);
}; };
/**
* struct drm_vram_mm - An instance of VRAM MM
* @vram_base: Base address of the managed video memory
* @vram_size: Size of the managed video memory in bytes
* @bdev: The TTM BO device.
* @funcs: TTM BO functions
*
* The fields &struct drm_vram_mm.vram_base and
* &struct drm_vram_mm.vrm_size are managed by VRAM MM, but are
* available for public read access. Use the field
* &struct drm_vram_mm.bdev to access the TTM BO device.
*/
struct drm_vram_mm {
uint64_t vram_base;
size_t vram_size;
struct ttm_bo_device bdev;
const struct drm_vram_mm_funcs *funcs;
};
/**
* drm_vram_mm_of_bdev() - \
Returns the container of type &struct ttm_bo_device for field bdev.
* @bdev: the TTM BO device
*
* Returns:
* The containing instance of &struct drm_vram_mm
*/
static inline struct drm_vram_mm *drm_vram_mm_of_bdev(
struct ttm_bo_device *bdev)
{
return container_of(bdev, struct drm_vram_mm, bdev);
}
int drm_vram_mm_debugfs_init(struct drm_minor *minor);
int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs);
void drm_vram_mm_cleanup(struct drm_vram_mm *vmm);
int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
struct drm_vram_mm *vmm);
/*
* Helpers for integration with struct drm_device
*/
struct drm_vram_mm *drm_vram_helper_alloc_mm(
struct drm_device *dev, uint64_t vram_base, size_t vram_size,
const struct drm_vram_mm_funcs *funcs);
void drm_vram_helper_release_mm(struct drm_device *dev);
/*
* Helpers for &struct file_operations
*/
int drm_vram_mm_file_operations_mmap(
struct file *filp, struct vm_area_struct *vma);
/**
* define DRM_VRAM_MM_FILE_OPERATIONS - default callback functions for \
&struct file_operations
*
* Drivers that use VRAM MM can use this macro to initialize
* &struct file_operations with default functions.
*/
#define DRM_VRAM_MM_FILE_OPERATIONS \
.llseek = no_llseek, \
.read = drm_read, \
.poll = drm_poll, \
.unlocked_ioctl = drm_ioctl, \
.compat_ioctl = drm_compat_ioctl, \
.mmap = drm_vram_mm_file_operations_mmap, \
.open = drm_open, \
.release = drm_release \
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment