summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/drm_vma_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_vma_manager.c')
-rw-r--r--drivers/gpu/drm/drm_vma_manager.c106
1 files changed, 66 insertions, 40 deletions
diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c
index d9100b565198..58659c16874c 100644
--- a/drivers/gpu/drm/drm_vma_manager.c
+++ b/drivers/gpu/drm/drm_vma_manager.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
/*
* Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
* Copyright (c) 2012 David Airlie <airlied@linux.ie>
@@ -22,9 +23,7 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include <drm/drmP.h>
-#include <drm/drm_mm.h>
-#include <drm/drm_vma_manager.h>
+#include <linux/export.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/rbtree.h>
@@ -32,6 +31,9 @@
#include <linux/spinlock.h>
#include <linux/types.h>
+#include <drm/drm_mm.h>
+#include <drm/drm_vma_manager.h>
+
/**
* DOC: vma offset manager
*
@@ -102,10 +104,7 @@ EXPORT_SYMBOL(drm_vma_offset_manager_init);
*/
void drm_vma_offset_manager_destroy(struct drm_vma_offset_manager *mgr)
{
- /* take the lock to protect against buggy drivers */
- write_lock(&mgr->vm_lock);
drm_mm_takedown(&mgr->vm_addr_space_mm);
- write_unlock(&mgr->vm_lock);
}
EXPORT_SYMBOL(drm_vma_offset_manager_destroy);
@@ -147,7 +146,7 @@ struct drm_vma_offset_node *drm_vma_offset_lookup_locked(struct drm_vma_offset_m
struct rb_node *iter;
unsigned long offset;
- iter = mgr->vm_addr_space_mm.interval_tree.rb_node;
+ iter = mgr->vm_addr_space_mm.interval_tree.rb_root.rb_node;
best = NULL;
while (likely(iter)) {
@@ -203,21 +202,16 @@ EXPORT_SYMBOL(drm_vma_offset_lookup_locked);
int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
struct drm_vma_offset_node *node, unsigned long pages)
{
- int ret;
+ int ret = 0;
write_lock(&mgr->vm_lock);
- if (drm_mm_node_allocated(&node->vm_node)) {
- ret = 0;
- goto out_unlock;
- }
+ if (!drm_mm_node_allocated(&node->vm_node))
+ ret = drm_mm_insert_node(&mgr->vm_addr_space_mm,
+ &node->vm_node, pages);
- ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node, pages);
- if (ret)
- goto out_unlock;
-
-out_unlock:
write_unlock(&mgr->vm_lock);
+
return ret;
}
EXPORT_SYMBOL(drm_vma_offset_add);
@@ -247,27 +241,8 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr,
}
EXPORT_SYMBOL(drm_vma_offset_remove);
-/**
- * drm_vma_node_allow - Add open-file to list of allowed users
- * @node: Node to modify
- * @tag: Tag of file to remove
- *
- * Add @tag to the list of allowed open-files for this node. If @tag is
- * already on this list, the ref-count is incremented.
- *
- * The list of allowed-users is preserved across drm_vma_offset_add() and
- * drm_vma_offset_remove() calls. You may even call it if the node is currently
- * not added to any offset-manager.
- *
- * You must remove all open-files the same number of times as you added them
- * before destroying the node. Otherwise, you will leak memory.
- *
- * This is locked against concurrent access internally.
- *
- * RETURNS:
- * 0 on success, negative error code on internal failure (out-of-mem)
- */
-int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
+static int vma_node_allow(struct drm_vma_offset_node *node,
+ struct drm_file *tag, bool ref_counted)
{
struct rb_node **iter;
struct rb_node *parent = NULL;
@@ -289,7 +264,8 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb);
if (tag == entry->vm_tag) {
- entry->vm_count++;
+ if (ref_counted)
+ entry->vm_count++;
goto unlock;
} else if (tag > entry->vm_tag) {
iter = &(*iter)->rb_right;
@@ -314,9 +290,59 @@ unlock:
kfree(new);
return ret;
}
+
+/**
+ * drm_vma_node_allow - Add open-file to list of allowed users
+ * @node: Node to modify
+ * @tag: Tag of file to remove
+ *
+ * Add @tag to the list of allowed open-files for this node. If @tag is
+ * already on this list, the ref-count is incremented.
+ *
+ * The list of allowed-users is preserved across drm_vma_offset_add() and
+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
+ * not added to any offset-manager.
+ *
+ * You must remove all open-files the same number of times as you added them
+ * before destroying the node. Otherwise, you will leak memory.
+ *
+ * This is locked against concurrent access internally.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on internal failure (out-of-mem)
+ */
+int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag)
+{
+ return vma_node_allow(node, tag, true);
+}
EXPORT_SYMBOL(drm_vma_node_allow);
/**
+ * drm_vma_node_allow_once - Add open-file to list of allowed users
+ * @node: Node to modify
+ * @tag: Tag of file to remove
+ *
+ * Add @tag to the list of allowed open-files for this node.
+ *
+ * The list of allowed-users is preserved across drm_vma_offset_add() and
+ * drm_vma_offset_remove() calls. You may even call it if the node is currently
+ * not added to any offset-manager.
+ *
+ * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke()
+ * should only be called once after this.
+ *
+ * This is locked against concurrent access internally.
+ *
+ * RETURNS:
+ * 0 on success, negative error code on internal failure (out-of-mem)
+ */
+int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag)
+{
+ return vma_node_allow(node, tag, false);
+}
+EXPORT_SYMBOL(drm_vma_node_allow_once);
+
+/**
* drm_vma_node_revoke - Remove open-file from list of allowed users
* @node: Node to modify
* @tag: Tag of file to remove
@@ -368,7 +394,7 @@ EXPORT_SYMBOL(drm_vma_node_revoke);
* This is locked against concurrent access internally.
*
* RETURNS:
- * true iff @filp is on the list
+ * true if @filp is on the list
*/
bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node,
struct drm_file *tag)