aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-08-30 15:08:40 +0200
committerThomas Hellstrom <thomas-at-tungstengraphics-dot-com>2006-08-30 15:08:40 +0200
commit14a835be616183e733a2d6a7dcc697b8a6f46caf (patch)
treeadaa844d3d5955681442df5032c4ef8b76683f1d
parente47a4fda2ef7aada45b7799ad20e8012102dc12e (diff)
Buffer object mapping and mapping synchronization for multiple clients.
-rw-r--r--libdrm/xf86drm.c103
-rw-r--r--libdrm/xf86mm.h8
-rw-r--r--linux-core/drm_bo.c3
-rw-r--r--linux-core/drm_object.c4
-rw-r--r--linux-core/drm_vm.c1
5 files changed, 104 insertions, 15 deletions
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index c9005c41..f592ff2a 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -2606,10 +2606,10 @@ int drmBOCreate(int fd, drmTTM *ttm, unsigned long start, unsigned long size,
buf->flags = rep->flags;
buf->size = rep->size;
buf->offset = rep->offset;
- buf->map_handle = rep->arg_handle;
- buf->map_flags = rep->map_flags;
- buf->map_virtual = NULL;
- buf->map_count = 0;
+ buf->mapHandle = rep->arg_handle;
+ buf->mapFlags = rep->map_flags;
+ buf->mapVirtual = NULL;
+ buf->mapCount = 0;
buf->virtual = NULL;
buf->mask = rep->mask;
buf->hint = rep->hint;
@@ -2666,13 +2666,14 @@ int drmBOReference(int fd, unsigned handle, drmBO *buf)
buf->flags = rep->flags;
buf->size = rep->size;
buf->offset = rep->offset;
- buf->map_handle = rep->arg_handle;
- buf->map_flags = rep->map_flags;
- buf->map_virtual = NULL;
- buf->map_count = 0;
+ buf->mapHandle = rep->arg_handle;
+ buf->mapFlags = rep->map_flags;
+ buf->mapVirtual = NULL;
+ buf->mapCount = 0;
buf->virtual = NULL;
buf->mask = rep->mask;
buf->hint = rep->hint;
+ buf->start = rep->buffer_start;
return 0;
}
@@ -2699,6 +2700,92 @@ int drmBOUnReference(int fd, drmBO *buf)
return 0;
}
+/*
+ *
+ */
+
+int drmBOMap(int fd, drmBO *buf, unsigned map_flags, void **address)
+{
+
+ drm_bo_arg_t arg;
+ drm_bo_arg_request_t *req = &arg.req;
+ drm_bo_arg_reply_t *rep = &arg.rep;
+ int ret = 0;
+
+ /*
+ * Make sure we have a virtual address of the buffer.
+ */
+
+ if (!buf->mapVirtual) {
+ if (buf->mapCount == 0) {
+ drmAddress virtual;
+ ret = drmMap(fd, buf->mapHandle, buf->size + buf->start, &virtual);
+ if (ret)
+ return ret;
+ ++buf->mapCount;
+ buf->mapVirtual = virtual;
+ buf->virtual = ((char *) virtual) + buf->start;
+ fprintf(stderr,"Mapvirtual, virtual: 0x%08x 0x%08x\n",
+ buf->mapVirtual, buf->virtual);
+ }
+ }
+
+ req->handle = buf->handle;
+ req->mask = map_flags;
+ req->op = drm_bo_map;
+ req->next = 0;
+
+ /*
+ * May hang if the buffer object is busy.
+ * This IOCTL synchronizes the buffer.
+ */
+
+ do {
+ ret = ioctl(fd, DRM_IOCTL_BUFOBJ, &arg);
+ } while (ret != 0 && errno == EAGAIN);
+
+ if (ret || !rep->handled || rep->ret) {
+ if (--buf->mapCount == 0) {
+ (void )drmUnmap(buf->mapVirtual, buf->start + buf->size);
+ }
+ }
+ if (ret)
+ return ret;
+ if (!rep->handled)
+ return -EFAULT;
+ if (rep->ret)
+ return rep->ret;
+
+ *address = buf->virtual;
+
+ return 0;
+}
+
+int drmBOUnmap(int fd, drmBO *buf)
+{
+ drm_bo_arg_t arg;
+ drm_bo_arg_request_t *req = &arg.req;
+
+ if (buf->mapCount == 0) {
+ return -EINVAL;
+ }
+
+ if (--buf->mapCount == 0) {
+ (void) drmUnmap(buf->mapVirtual, buf->start + buf->size);
+ }
+
+ req->handle = buf->handle;
+ req->op = drm_bo_unmap;
+ req->next = 0;
+
+ if (ioctl(fd, DRM_IOCTL_BUFOBJ, &arg)) {
+ return -errno;
+ }
+
+ return 0;
+}
+
+
int drmMMInit(int fd, unsigned long vramPOffset, unsigned long vramPSize,
unsigned long ttPOffset, unsigned long ttPSize)
{
diff --git a/libdrm/xf86mm.h b/libdrm/xf86mm.h
index 8711a144..c811892f 100644
--- a/libdrm/xf86mm.h
+++ b/libdrm/xf86mm.h
@@ -85,17 +85,17 @@ typedef struct _drmMMListHead
typedef struct _drmBO{
drm_bo_type_t type;
unsigned handle;
- drm_handle_t map_handle;
+ drm_handle_t mapHandle;
unsigned flags;
unsigned mask;
unsigned hint;
- unsigned map_flags;
+ unsigned mapFlags;
unsigned long size;
unsigned long offset;
unsigned long start;
void *virtual;
- void *map_virtual;
- int map_count;
+ void *mapVirtual;
+ int mapCount;
drmTTM *ttm;
} drmBO;
diff --git a/linux-core/drm_bo.c b/linux-core/drm_bo.c
index 5f557d55..aa59238f 100644
--- a/linux-core/drm_bo.c
+++ b/linux-core/drm_bo.c
@@ -513,8 +513,11 @@ static int drm_buffer_object_unmap(drm_file_t * priv, uint32_t handle)
goto out;
}
+ DRM_ERROR("Removing ref object\n");
drm_remove_ref_object(priv, ro);
+ DRM_ERROR("Deregistering usage\n");
drm_bo_usage_deref_locked(dev, bo);
+ DRM_ERROR("Done\n");
out:
mutex_unlock(&dev->struct_mutex);
return ret;
diff --git a/linux-core/drm_object.c b/linux-core/drm_object.c
index b928c01e..e1b79101 100644
--- a/linux-core/drm_object.c
+++ b/linux-core/drm_object.c
@@ -108,9 +108,6 @@ static int drm_object_ref_action(drm_file_t * priv, drm_user_object_t * ro,
break;
default:
if (!ro->ref_struct_locked) {
- DRM_ERROR("Register object called without register"
- " capabilities\n");
- ret = -EINVAL;
break;
} else {
ro->ref_struct_locked(priv, ro, action);
@@ -164,6 +161,7 @@ int drm_add_ref_object(drm_file_t * priv, drm_user_object_t * referenced_object,
atomic_set(&item->refcount, 1);
item->hash.key = (unsigned long)referenced_object;
ret = drm_ht_insert_item(ht, &item->hash);
+ item->unref_action = ref_action;
if (ret)
goto out;
diff --git a/linux-core/drm_vm.c b/linux-core/drm_vm.c
index 7163341d..69391058 100644
--- a/linux-core/drm_vm.c
+++ b/linux-core/drm_vm.c
@@ -713,6 +713,7 @@ static void drm_vm_ttm_close(struct vm_area_struct *vma)
dev = ttm->dev;
mutex_lock(&dev->struct_mutex);
drm_ttm_delete_mm(ttm, vma->vm_mm);
+ list_del(&ttm_vma->head);
drm_free(ttm_vma, sizeof(*ttm_vma), DRM_MEM_VMAS);
if (atomic_dec_and_test(&ttm->vma_count)) {
if (ttm->destroy) {