summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libdrm/Makefile.am2
-rw-r--r--libdrm/xf86drm.c30
-rw-r--r--libdrm/xf86drm.h2
-rw-r--r--libdrm/xf86mm.h9
-rw-r--r--linux-core/drmP.h5
-rw-r--r--linux-core/drm_bo.c123
-rw-r--r--linux-core/drm_drv.c3
-rw-r--r--shared-core/drm.h19
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 <stddef.h>
-#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
/*@}*/