diff options
author | Inki Dae <inki.dae@samsung.com> | 2014-11-25 18:01:36 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-11-25 03:20:32 -0800 |
commit | 135b72a7be9a484e8e2576bf3c49a51445b76bce (patch) | |
tree | 1fcd3dbb5b25255795f73c1076805a1c7e8e215a | |
parent | 8c34dbd28cfce4e09ebec8bdf1b820924c2df45b (diff) | |
download | linux-3.10-135b72a7be9a484e8e2576bf3c49a51445b76bce.tar.gz linux-3.10-135b72a7be9a484e8e2576bf3c49a51445b76bce.tar.bz2 linux-3.10-135b72a7be9a484e8e2576bf3c49a51445b76bce.zip |
dma-buf/dmabuf-sync: add dmabuf_sync_reference_reservation functionsubmit/tizen/20141126.081420accepted/tizen/mobile/20141126.082557accepted/tizen/common/20141126.162632
This patch adds dmabuf_sync_reference_reservation function that
can get/drop a reference to all fences added to reservation_object of
a given dmabuf object, and calls it before blocked and after waked up
to avoid null pointer dereference.
Change-Id: I32f31b5a54e233d4a06b9915d26b04cda4e31d01
Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r-- | drivers/dma-buf/dmabuf-sync.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/dma-buf/dmabuf-sync.c b/drivers/dma-buf/dmabuf-sync.c index 5f51e17b12a..d654669afc9 100644 --- a/drivers/dma-buf/dmabuf-sync.c +++ b/drivers/dma-buf/dmabuf-sync.c @@ -608,6 +608,47 @@ out: spin_unlock_irqrestore(&orders_lock, o_flags); } +static void dmabuf_sync_reference_reservation(struct dma_buf *dmabuf, + bool reference) +{ + struct reservation_object *obj = dmabuf->resv; + struct reservation_object_list *fobj; + struct fence *fence; + + rcu_read_lock(); + + fobj = rcu_dereference(obj->fence); + if (fobj) { + int i; + + for (i = 0; i < fobj->shared_count; i++) { + fence = rcu_dereference(fobj->shared[i]); + if (!fence) { + WARN_ON(1); + continue; + } + + if (reference) + fence_get_rcu(fence); + else + fence_put(fence); + } + } + + fence = rcu_dereference(obj->fence_excl); + if (!fence) { + rcu_read_unlock(); + return; + } + + if (reference) + fence_get_rcu(fence); + else + fence_put(fence); + + rcu_read_unlock(); +} + /* * is_higher_priority_than_current - check if a given sobj was requested * the first. @@ -690,6 +731,7 @@ long dmabuf_sync_wait_all(struct dmabuf_sync *sync) sf = sobj->sfence; dmabuf = sobj->dmabuf; + dmabuf_sync_reference_reservation(dmabuf, true); /* * It doesn't need to wait for other thread or threads @@ -730,6 +772,7 @@ go_back_to_wait: out_enable_signal: fence_enable_sw_signaling(&sf->base); dmabuf_sync_update(sobj); + dmabuf_sync_reference_reservation(dmabuf, false); dmabuf_sync_cache_ops(sobj); spin_lock_irqsave(&sync->lock, s_flags); @@ -788,6 +831,8 @@ long dmabuf_sync_wait(struct dma_buf *dmabuf, unsigned int ctx, sobj_get(sobj); spin_unlock_irqrestore(&orders_lock, o_flags); + dmabuf_sync_reference_reservation(dmabuf, true); + /* * It doesn't need to wait for other thread or threads * if there is no any sync object which has higher priority @@ -827,6 +872,7 @@ go_back_to_wait: out_enable_signal: fence_enable_sw_signaling(&sync->sfence.base); dmabuf_sync_update(sobj); + dmabuf_sync_reference_reservation(dmabuf, false); dmabuf_sync_cache_ops(sobj); return timeout; |