diff options
author | Dave Airlie <airlied@redhat.com> | 2016-10-10 16:36:16 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-10-10 16:36:16 +1000 |
commit | 9c704d14386dc1deeb695f2a180f9a00f23fa650 (patch) | |
tree | fd4b11b8119a0d8fca8a3ccf45e76e2334b86b8e /drivers/gpu/drm/drm_prime.c | |
parent | a74feb65a451105bb9aba6ea695b7068b0690046 (diff) | |
parent | 0546d685f07cc4fc5748fd36e57d167877c2842d (diff) | |
download | linux-9c704d14386dc1deeb695f2a180f9a00f23fa650.tar.gz linux-9c704d14386dc1deeb695f2a180f9a00f23fa650.tar.xz |
Merge tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel into drm-next
Another attempt, this time rebased and without the pipe crc patches:
- display_info cleanups from Ville
- make prime/gem lookups faster with rbtrees (Chris)
- misc stuff all over
* tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel:
drm/rockchip: analogix_dp: Refuse to enable PSR if panel doesn't support it
drm/bridge: analogix_dp: Add analogix_dp_psr_supported
drm/fb-helper: add DRM_FB_HELPER_DEFAULT_OPS for fb_ops
drm: Document caveats around atomic event handling
uapi: add missing install of sync_file.h
drm: Simplify drm_printk to reduce object size quite a bit
drm/i915: Account for sink max TMDS clock when checking the port clock
drm/i915: Replace a bunch of connector->base.display_info with a local variable
drm/edid: Move dvi_dual/max_tmds_clock parsing out from drm_edid_to_eld()
drm/edid: Clear the old cea_rev when there's no CEA extension in the new EDID
drm/edid: Reduce the number of times we parse the CEA extension block
drm/edid: Don't pass around drm_display_info needlessly
drm/edid: Move dvi_dual/max_tmds_clock to drm_display_info
drm/edid: Make max_tmds_clock kHz instead of MHz
drm/edid: Clear old dvi_dual/max_tmds_clock before parsing the new EDID
drm/edid: Clear old audio latency values before parsing the new EDID
drm: Convert prime dma-buf <-> handle to rbtree
drm/mediatek: mark symbols static where possible
drm/rockchip: mark symbols static where possible
drm/rockchip: add missing header dependencies
Diffstat (limited to 'drivers/gpu/drm/drm_prime.c')
-rw-r--r-- | drivers/gpu/drm/drm_prime.c | 85 |
1 files changed, 74 insertions, 11 deletions
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 780589b420a4..57201d68cf61 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -28,6 +28,7 @@ #include <linux/export.h> #include <linux/dma-buf.h> +#include <linux/rbtree.h> #include <drm/drmP.h> #include <drm/drm_gem.h> @@ -61,9 +62,11 @@ */ struct drm_prime_member { - struct list_head entry; struct dma_buf *dma_buf; uint32_t handle; + + struct rb_node dmabuf_rb; + struct rb_node handle_rb; }; struct drm_prime_attachment { @@ -75,6 +78,7 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle) { struct drm_prime_member *member; + struct rb_node **p, *rb; member = kmalloc(sizeof(*member), GFP_KERNEL); if (!member) @@ -83,18 +87,56 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, get_dma_buf(dma_buf); member->dma_buf = dma_buf; member->handle = handle; - list_add(&member->entry, &prime_fpriv->head); + + rb = NULL; + p = &prime_fpriv->dmabufs.rb_node; + while (*p) { + struct drm_prime_member *pos; + + rb = *p; + pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb); + if (dma_buf > pos->dma_buf) + p = &rb->rb_right; + else + p = &rb->rb_left; + } + rb_link_node(&member->dmabuf_rb, rb, p); + rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs); + + rb = NULL; + p = &prime_fpriv->handles.rb_node; + while (*p) { + struct drm_prime_member *pos; + + rb = *p; + pos = rb_entry(rb, struct drm_prime_member, handle_rb); + if (handle > pos->handle) + p = &rb->rb_right; + else + p = &rb->rb_left; + } + rb_link_node(&member->handle_rb, rb, p); + rb_insert_color(&member->handle_rb, &prime_fpriv->handles); + return 0; } static struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv, uint32_t handle) { - struct drm_prime_member *member; + struct rb_node *rb; + + rb = prime_fpriv->handles.rb_node; + while (rb) { + struct drm_prime_member *member; - list_for_each_entry(member, &prime_fpriv->head, entry) { + member = rb_entry(rb, struct drm_prime_member, handle_rb); if (member->handle == handle) return member->dma_buf; + else if (member->handle < handle) + rb = rb->rb_right; + else + rb = rb->rb_left; } return NULL; @@ -104,14 +146,23 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri struct dma_buf *dma_buf, uint32_t *handle) { - struct drm_prime_member *member; + struct rb_node *rb; + + rb = prime_fpriv->dmabufs.rb_node; + while (rb) { + struct drm_prime_member *member; - list_for_each_entry(member, &prime_fpriv->head, entry) { + member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); if (member->dma_buf == dma_buf) { *handle = member->handle; return 0; + } else if (member->dma_buf < dma_buf) { + rb = rb->rb_right; + } else { + rb = rb->rb_left; } } + return -ENOENT; } @@ -166,13 +217,24 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf, void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) { - struct drm_prime_member *member, *safe; + struct rb_node *rb; - list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) { + rb = prime_fpriv->dmabufs.rb_node; + while (rb) { + struct drm_prime_member *member; + + member = rb_entry(rb, struct drm_prime_member, dmabuf_rb); if (member->dma_buf == dma_buf) { + rb_erase(&member->handle_rb, &prime_fpriv->handles); + rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs); + dma_buf_put(dma_buf); - list_del(&member->entry); kfree(member); + return; + } else if (member->dma_buf < dma_buf) { + rb = rb->rb_right; + } else { + rb = rb->rb_left; } } } @@ -759,12 +821,13 @@ EXPORT_SYMBOL(drm_prime_gem_destroy); void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) { - INIT_LIST_HEAD(&prime_fpriv->head); mutex_init(&prime_fpriv->lock); + prime_fpriv->dmabufs = RB_ROOT; + prime_fpriv->handles = RB_ROOT; } void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) { /* by now drm_gem_release should've made sure the list is empty */ - WARN_ON(!list_empty(&prime_fpriv->head)); + WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)); } |