From e47a4fda2ef7aada45b7799ad20e8012102dc12e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 30 Aug 2006 13:04:08 +0200 Subject: Memory manager init and takedown. --- libdrm/Makefile.am | 2 +- libdrm/xf86drm.c | 30 ++++++++++++- libdrm/xf86drm.h | 2 + libdrm/xf86mm.h | 9 +++- linux-core/drmP.h | 5 ++- linux-core/drm_bo.c | 123 +++++++++++++++++++++++++++++++++++++++++++++------ linux-core/drm_drv.c | 3 ++ shared-core/drm.h | 19 ++++++++ 8 files changed, 175 insertions(+), 18 deletions(-) diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am index b12e87fa..91a7e5dc 100644 --- a/libdrm/Makefile.am +++ b/libdrm/Makefile.am @@ -26,6 +26,6 @@ AM_CFLAGS = -I$(top_srcdir)/shared-core libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c libdrmincludedir = ${includedir} -libdrminclude_HEADERS = xf86drm.h +libdrminclude_HEADERS = xf86drm.h xf86mm.h EXTRA_DIST = ChangeLog TODO diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c index 3fccdf69..c9005c41 100644 --- a/libdrm/xf86drm.c +++ b/libdrm/xf86drm.c @@ -65,7 +65,6 @@ # define _DRM_FREE free # include "drm.h" #endif -#include "xf86mm.h" /* Not all systems have MAP_FAILED defined */ @@ -2582,6 +2581,7 @@ int drmBOCreate(int fd, drmTTM *ttm, unsigned long start, unsigned long size, buf->ttm = ttm; break; case drm_bo_type_dc: + req->buffer_start = start; break; case drm_bo_type_user: req->buffer_start = (unsigned long) user_buffer; @@ -2699,4 +2699,32 @@ int drmBOUnReference(int fd, drmBO *buf) return 0; } +int drmMMInit(int fd, unsigned long vramPOffset, unsigned long vramPSize, + unsigned long ttPOffset, unsigned long ttPSize) +{ + drm_mm_init_arg_t arg; + + arg.req.op = mm_init; + arg.req.vr_p_offset = vramPOffset; + arg.req.vr_p_size = vramPSize; + arg.req.tt_p_offset = vramPOffset; + arg.req.tt_p_size = vramPSize; + + if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) + return -errno; + + return 0; +} + +int drmMMTakedown(int fd) +{ + drm_mm_init_arg_t arg; + arg.req.op = mm_takedown; + + if (ioctl(fd, DRM_IOCTL_MM_INIT, &arg)) + return -errno; + + return 0; +} + #endif diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h index ca48bfbf..f257deda 100644 --- a/libdrm/xf86drm.h +++ b/libdrm/xf86drm.h @@ -670,4 +670,6 @@ extern int drmSLLookupNeighbors(void *l, unsigned long key, unsigned long *prev_key, void **prev_value, unsigned long *next_key, void **next_value); +#include "xf86mm.h" + #endif diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h index 08149d08..8711a144 100644 --- a/libdrm/xf86mm.h +++ b/libdrm/xf86mm.h @@ -29,7 +29,7 @@ #ifndef _XF86MM_H_ #define _XF86MM_H_ #include -#include "xf86drm.h" +#include "drm.h" /* * List macros heavily inspired by the Linux kernel @@ -114,5 +114,12 @@ typedef struct _drmBOList { drmMMListHead free; } drmBOList; +extern int drmBOCreate(int fd, drmTTM *ttm, unsigned long start, unsigned long size, + void *user_buffer, drm_bo_type_t type, unsigned mask, + unsigned hint, drmBO *buf); +extern int drmBODestroy(int fd, drmBO *buf); +extern int drmBOReference(int fd, unsigned handle, drmBO *buf); +extern int drmBOUnReference(int fd, drmBO *buf); + #endif diff --git a/linux-core/drmP.h b/linux-core/drmP.h index 63bcde2e..59926968 100644 --- a/linux-core/drmP.h +++ b/linux-core/drmP.h @@ -775,7 +775,9 @@ typedef struct drm_fence_manager{ typedef struct drm_buffer_manager{ int initialized; - struct mutex bm_mutex; + int has_vram; + int has_tt; + struct mutex mutex; drm_mm_t tt_manager; struct list_head tt_lru; drm_mm_t vram_manager; @@ -1363,6 +1365,7 @@ extern int drm_fence_ioctl(DRM_IOCTL_ARGS); */ extern int drm_bo_ioctl(DRM_IOCTL_ARGS); +extern int drm_mm_init_ioctl(DRM_IOCTL_ARGS); /* Inline replacements for DRM_IOREMAP macros */ diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c index 24389447..5f557d55 100644 --- a/linux-core/drm_bo.c +++ b/linux-core/drm_bo.c @@ -66,7 +66,7 @@ int drm_fence_buffer_objects(drm_file_t * priv) drm_fence_object_t *fence; int ret; - mutex_lock(&bm->bm_mutex); + mutex_lock(&bm->mutex); list_for_each_entry(entry, &bm->unfenced, head) { BUG_ON(!entry->unfenced); @@ -75,21 +75,21 @@ int drm_fence_buffer_objects(drm_file_t * priv) } if (!count) { - mutex_unlock(&bm->bm_mutex); + mutex_unlock(&bm->mutex); return 0; } fence = drm_calloc(1, sizeof(*fence), DRM_MEM_FENCE); if (!fence) { - mutex_unlock(&bm->bm_mutex); + mutex_unlock(&bm->mutex); return -ENOMEM; } ret = drm_fence_object_init(dev, fence_flags, 1, fence); if (ret) { drm_free(fence, sizeof(*fence), DRM_MEM_FENCE); - mutex_unlock(&bm->bm_mutex); + mutex_unlock(&bm->mutex); return ret; } @@ -111,7 +111,7 @@ int drm_fence_buffer_objects(drm_file_t * priv) mutex_lock(&dev->struct_mutex); atomic_add(count - 1, &fence->usage); mutex_unlock(&dev->struct_mutex); - mutex_unlock(&bm->bm_mutex); + mutex_unlock(&bm->mutex); return 0; } @@ -179,11 +179,12 @@ static void drm_bo_destroy_locked(drm_device_t * dev, drm_buffer_object_t * bo) drm_mm_put_block(&bm->vram_manager, bo->vram); bo->vram = NULL; } - - /* - * FIXME: Destroy ttm. - */ - + if (bo->ttm_region) { + drm_destroy_ttm_region(bo->ttm_region); + } + if (bo->ttm_object) { + drm_ttm_object_deref_locked(dev, bo->ttm_object); + } drm_free(bo, sizeof(*bo), DRM_MEM_BUFOBJ); } @@ -356,8 +357,11 @@ drm_buffer_object_t *drm_lookup_buffer_object(drm_file_t * priv, uo = drm_lookup_user_object(priv, handle); - if (!uo || (uo->type != drm_buffer_type)) + if (!uo || (uo->type != drm_buffer_type)) { + DRM_ERROR("Could not find buffer object 0x%08x\n", + handle); return NULL; + } if (check_owner && priv != uo->owner) { if (!drm_lookup_ref_object(priv, uo, _DRM_REF_USE)) @@ -541,9 +545,10 @@ static void drm_buffer_user_object_unmap(drm_file_t * priv, } } -static int drm_buffer_object_validate(drm_device_t * dev, +static int drm_buffer_object_validate(drm_device_t * dev, uint32_t new_flags, drm_buffer_object_t * bo) { + bo->flags = new_flags; return 0; } @@ -574,14 +579,18 @@ static int drm_bo_add_ttm(drm_file_t * priv, drm_buffer_object_t * bo, mutex_lock(&dev->struct_mutex); to = drm_lookup_ttm_object(priv, ttm_handle, 1); mutex_unlock(&dev->struct_mutex); - if (!to) + if (!to) { + DRM_ERROR("Could not find TTM object\n"); ret = -EINVAL; + } break; case drm_bo_type_user: case drm_bo_type_fake: break; default: + DRM_ERROR("Illegal buffer object type\n"); ret = -EINVAL; + break; } if (ret) { @@ -656,7 +665,7 @@ int drm_buffer_object_create(drm_file_t * priv, bo->mask = mask; bo->hint = hint; - ret = drm_buffer_object_validate(dev, bo); + ret = drm_buffer_object_validate(dev, new_flags, bo); if (ret) goto out_err; @@ -805,3 +814,89 @@ int drm_bo_ioctl(DRM_IOCTL_ARGS) return 0; } + +static void drm_bo_clean_mm(drm_file_t *priv) +{ +} + + +int drm_mm_init_ioctl(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + + int ret = 0; + drm_mm_init_arg_t arg; + drm_buffer_manager_t *bm = &dev->bm; + drm_bo_driver_t *driver = dev->driver->bo_driver; + + if (!driver) { + DRM_ERROR("Buffer objects is not supported by this driver\n"); + return -EINVAL; + } + + DRM_COPY_FROM_USER_IOCTL(arg, (void __user *)data, sizeof(arg)); + + switch(arg.req.op) { + case mm_init: + if (bm->initialized) { + DRM_ERROR("Memory manager already initialized\n"); + return -EINVAL; + } + mutex_init(&bm->mutex); + mutex_lock(&bm->mutex); + bm->has_vram = 0; + bm->has_tt = 0; + + if (arg.req.vr_p_size) { + ret = drm_mm_init(&bm->vram_manager, + arg.req.vr_p_offset, + arg.req.vr_p_size); + bm->has_vram = 1; + if (ret) + break; + } + + if (arg.req.tt_p_size) { + ret = drm_mm_init(&bm->tt_manager, + arg.req.tt_p_offset, + arg.req.tt_p_size); + bm->has_tt = 1; + if (ret) { + if (bm->has_vram) + drm_mm_takedown(&bm->vram_manager); + break; + } + } + arg.rep.mm_sarea = 0; + + INIT_LIST_HEAD(&bm->vram_lru); + INIT_LIST_HEAD(&bm->tt_lru); + INIT_LIST_HEAD(&bm->unfenced); + INIT_LIST_HEAD(&bm->ddestroy); + + bm->initialized = 1; + break; + case mm_takedown: + if (!bm->initialized) { + DRM_ERROR("Memory manager was not initialized\n"); + return -EINVAL; + } + mutex_lock(&bm->mutex); + drm_bo_clean_mm(priv); + if (bm->has_vram) + drm_mm_takedown(&bm->vram_manager); + if (bm->has_tt) + drm_mm_takedown(&bm->tt_manager); + bm->initialized = 0; + break; + default: + return -EINVAL; + } + + mutex_unlock(&bm->mutex); + if (ret) + return ret; + + DRM_COPY_TO_USER_IOCTL((void __user *)data, arg, sizeof(arg)); + return 0; +} diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c index f27a7aff..62df6803 100644 --- a/linux-core/drm_drv.c +++ b/linux-core/drm_drv.c @@ -121,6 +121,9 @@ static drm_ioctl_desc_t drm_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, [DRM_IOCTL_NR(DRM_IOCTL_FENCE)] = {drm_fence_ioctl, DRM_AUTH}, [DRM_IOCTL_NR(DRM_IOCTL_TTM)] = {drm_ttm_ioctl, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_IOCTL_BUFOBJ)] = {drm_bo_ioctl, DRM_AUTH}, + [DRM_IOCTL_NR(DRM_IOCTL_MM_INIT)] = {drm_mm_init_ioctl, + DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}, }; #define DRIVER_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/shared-core/drm.h b/shared-core/drm.h index f6abfeb9..f900dd51 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -747,8 +747,26 @@ typedef union drm_bo_arg{ drm_bo_arg_request_t req; drm_bo_arg_reply_t rep; } drm_bo_arg_t; + +typedef union drm_mm_init_arg{ + struct { + enum { + mm_init, + mm_takedown, + mm_query + } op; + drm_u64_t vr_p_offset; + drm_u64_t vr_p_size; + drm_u64_t tt_p_offset; + drm_u64_t tt_p_size; + } req; + struct { + drm_handle_t mm_sarea; + } rep; +} drm_mm_init_arg_t; #endif + /** * \name Ioctls Definitions */ @@ -818,6 +836,7 @@ typedef union drm_bo_arg{ #define DRM_IOCTL_FENCE DRM_IOWR(0x3b, drm_fence_arg_t) #define DRM_IOCTL_TTM DRM_IOWR(0x3c, drm_ttm_arg_t) #define DRM_IOCTL_BUFOBJ DRM_IOWR(0x3d, drm_bo_arg_t) +#define DRM_IOCTL_MM_INIT DRM_IOWR(0x3e, drm_mm_init_arg_t) #endif /*@}*/ -- cgit v1.2.3