LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915 - i915_sw_fence.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 228 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 19 0.0 %
Branches: 0 98 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * SPDX-License-Identifier: MIT
       3                 :            :  *
       4                 :            :  * (C) Copyright 2016 Intel Corporation
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <linux/slab.h>
       8                 :            : #include <linux/dma-fence.h>
       9                 :            : #include <linux/irq_work.h>
      10                 :            : #include <linux/dma-resv.h>
      11                 :            : 
      12                 :            : #include "i915_sw_fence.h"
      13                 :            : #include "i915_selftest.h"
      14                 :            : 
      15                 :            : #if IS_ENABLED(CONFIG_DRM_I915_DEBUG)
      16                 :            : #define I915_SW_FENCE_BUG_ON(expr) BUG_ON(expr)
      17                 :            : #else
      18                 :            : #define I915_SW_FENCE_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr)
      19                 :            : #endif
      20                 :            : 
      21                 :            : #define I915_SW_FENCE_FLAG_ALLOC BIT(3) /* after WQ_FLAG_* for safety */
      22                 :            : 
      23                 :            : static DEFINE_SPINLOCK(i915_sw_fence_lock);
      24                 :            : 
      25                 :            : enum {
      26                 :            :         DEBUG_FENCE_IDLE = 0,
      27                 :            :         DEBUG_FENCE_NOTIFY,
      28                 :            : };
      29                 :            : 
      30                 :          0 : static void *i915_sw_fence_debug_hint(void *addr)
      31                 :            : {
      32                 :          0 :         return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK);
      33                 :            : }
      34                 :            : 
      35                 :            : #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
      36                 :            : 
      37                 :            : static struct debug_obj_descr i915_sw_fence_debug_descr = {
      38                 :            :         .name = "i915_sw_fence",
      39                 :            :         .debug_hint = i915_sw_fence_debug_hint,
      40                 :            : };
      41                 :            : 
      42                 :            : static inline void debug_fence_init(struct i915_sw_fence *fence)
      43                 :            : {
      44                 :            :         debug_object_init(fence, &i915_sw_fence_debug_descr);
      45                 :            : }
      46                 :            : 
      47                 :            : static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
      48                 :            : {
      49                 :            :         debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr);
      50                 :            : }
      51                 :            : 
      52                 :            : static inline void debug_fence_activate(struct i915_sw_fence *fence)
      53                 :            : {
      54                 :            :         debug_object_activate(fence, &i915_sw_fence_debug_descr);
      55                 :            : }
      56                 :            : 
      57                 :            : static inline void debug_fence_set_state(struct i915_sw_fence *fence,
      58                 :            :                                          int old, int new)
      59                 :            : {
      60                 :            :         debug_object_active_state(fence, &i915_sw_fence_debug_descr, old, new);
      61                 :            : }
      62                 :            : 
      63                 :            : static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
      64                 :            : {
      65                 :            :         debug_object_deactivate(fence, &i915_sw_fence_debug_descr);
      66                 :            : }
      67                 :            : 
      68                 :            : static inline void debug_fence_destroy(struct i915_sw_fence *fence)
      69                 :            : {
      70                 :            :         debug_object_destroy(fence, &i915_sw_fence_debug_descr);
      71                 :            : }
      72                 :            : 
      73                 :            : static inline void debug_fence_free(struct i915_sw_fence *fence)
      74                 :            : {
      75                 :            :         debug_object_free(fence, &i915_sw_fence_debug_descr);
      76                 :            :         smp_wmb(); /* flush the change in state before reallocation */
      77                 :            : }
      78                 :            : 
      79                 :            : static inline void debug_fence_assert(struct i915_sw_fence *fence)
      80                 :            : {
      81                 :            :         debug_object_assert_init(fence, &i915_sw_fence_debug_descr);
      82                 :            : }
      83                 :            : 
      84                 :            : #else
      85                 :            : 
      86                 :          0 : static inline void debug_fence_init(struct i915_sw_fence *fence)
      87                 :            : {
      88                 :          0 : }
      89                 :            : 
      90                 :            : static inline void debug_fence_init_onstack(struct i915_sw_fence *fence)
      91                 :            : {
      92                 :            : }
      93                 :            : 
      94                 :          0 : static inline void debug_fence_activate(struct i915_sw_fence *fence)
      95                 :            : {
      96                 :          0 : }
      97                 :            : 
      98                 :          0 : static inline void debug_fence_set_state(struct i915_sw_fence *fence,
      99                 :            :                                          int old, int new)
     100                 :            : {
     101                 :          0 : }
     102                 :            : 
     103                 :          0 : static inline void debug_fence_deactivate(struct i915_sw_fence *fence)
     104                 :            : {
     105                 :          0 : }
     106                 :            : 
     107                 :          0 : static inline void debug_fence_destroy(struct i915_sw_fence *fence)
     108                 :            : {
     109                 :          0 : }
     110                 :            : 
     111                 :            : static inline void debug_fence_free(struct i915_sw_fence *fence)
     112                 :            : {
     113                 :            : }
     114                 :            : 
     115                 :          0 : static inline void debug_fence_assert(struct i915_sw_fence *fence)
     116                 :            : {
     117                 :          0 : }
     118                 :            : 
     119                 :            : #endif
     120                 :            : 
     121                 :          0 : static int __i915_sw_fence_notify(struct i915_sw_fence *fence,
     122                 :            :                                   enum i915_sw_fence_notify state)
     123                 :            : {
     124                 :          0 :         i915_sw_fence_notify_t fn;
     125                 :            : 
     126                 :          0 :         fn = (i915_sw_fence_notify_t)(fence->flags & I915_SW_FENCE_MASK);
     127                 :          0 :         return fn(fence, state);
     128                 :            : }
     129                 :            : 
     130                 :            : #ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS
     131                 :            : void i915_sw_fence_fini(struct i915_sw_fence *fence)
     132                 :            : {
     133                 :            :         debug_fence_free(fence);
     134                 :            : }
     135                 :            : #endif
     136                 :            : 
     137                 :          0 : static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence,
     138                 :            :                                         struct list_head *continuation)
     139                 :            : {
     140                 :          0 :         wait_queue_head_t *x = &fence->wait;
     141                 :          0 :         wait_queue_entry_t *pos, *next;
     142                 :          0 :         unsigned long flags;
     143                 :            : 
     144                 :          0 :         debug_fence_deactivate(fence);
     145                 :          0 :         atomic_set_release(&fence->pending, -1); /* 0 -> -1 [done] */
     146                 :            : 
     147                 :            :         /*
     148                 :            :          * To prevent unbounded recursion as we traverse the graph of
     149                 :            :          * i915_sw_fences, we move the entry list from this, the next ready
     150                 :            :          * fence, to the tail of the original fence's entry list
     151                 :            :          * (and so added to the list to be woken).
     152                 :            :          */
     153                 :            : 
     154                 :          0 :         spin_lock_irqsave_nested(&x->lock, flags, 1 + !!continuation);
     155         [ #  # ]:          0 :         if (continuation) {
     156         [ #  # ]:          0 :                 list_for_each_entry_safe(pos, next, &x->head, entry) {
     157         [ #  # ]:          0 :                         if (pos->func == autoremove_wake_function)
     158                 :          0 :                                 pos->func(pos, TASK_NORMAL, 0, continuation);
     159                 :            :                         else
     160                 :          0 :                                 list_move_tail(&pos->entry, continuation);
     161                 :            :                 }
     162                 :            :         } else {
     163                 :          0 :                 LIST_HEAD(extra);
     164                 :            : 
     165                 :          0 :                 do {
     166         [ #  # ]:          0 :                         list_for_each_entry_safe(pos, next, &x->head, entry) {
     167                 :          0 :                                 pos->func(pos,
     168                 :            :                                           TASK_NORMAL, fence->error,
     169                 :            :                                           &extra);
     170                 :            :                         }
     171                 :            : 
     172         [ #  # ]:          0 :                         if (list_empty(&extra))
     173                 :            :                                 break;
     174                 :            : 
     175         [ #  # ]:          0 :                         list_splice_tail_init(&extra, &x->head);
     176                 :            :                 } while (1);
     177                 :            :         }
     178                 :          0 :         spin_unlock_irqrestore(&x->lock, flags);
     179                 :            : 
     180                 :          0 :         debug_fence_assert(fence);
     181                 :          0 : }
     182                 :            : 
     183                 :          0 : static void __i915_sw_fence_complete(struct i915_sw_fence *fence,
     184                 :            :                                      struct list_head *continuation)
     185                 :            : {
     186                 :          0 :         debug_fence_assert(fence);
     187                 :            : 
     188         [ #  # ]:          0 :         if (!atomic_dec_and_test(&fence->pending))
     189                 :            :                 return;
     190                 :            : 
     191                 :          0 :         debug_fence_set_state(fence, DEBUG_FENCE_IDLE, DEBUG_FENCE_NOTIFY);
     192                 :            : 
     193         [ #  # ]:          0 :         if (__i915_sw_fence_notify(fence, FENCE_COMPLETE) != NOTIFY_DONE)
     194                 :            :                 return;
     195                 :            : 
     196                 :          0 :         debug_fence_set_state(fence, DEBUG_FENCE_NOTIFY, DEBUG_FENCE_IDLE);
     197                 :            : 
     198                 :          0 :         __i915_sw_fence_wake_up_all(fence, continuation);
     199                 :            : 
     200                 :          0 :         debug_fence_destroy(fence);
     201                 :          0 :         __i915_sw_fence_notify(fence, FENCE_FREE);
     202                 :            : }
     203                 :            : 
     204                 :          0 : void i915_sw_fence_complete(struct i915_sw_fence *fence)
     205                 :            : {
     206                 :          0 :         debug_fence_assert(fence);
     207                 :            : 
     208   [ #  #  #  # ]:          0 :         if (WARN_ON(i915_sw_fence_done(fence)))
     209                 :            :                 return;
     210                 :            : 
     211                 :          0 :         __i915_sw_fence_complete(fence, NULL);
     212                 :            : }
     213                 :            : 
     214                 :          0 : void i915_sw_fence_await(struct i915_sw_fence *fence)
     215                 :            : {
     216                 :          0 :         debug_fence_assert(fence);
     217         [ #  # ]:          0 :         WARN_ON(atomic_inc_return(&fence->pending) <= 1);
     218                 :          0 : }
     219                 :            : 
     220                 :          0 : void __i915_sw_fence_init(struct i915_sw_fence *fence,
     221                 :            :                           i915_sw_fence_notify_t fn,
     222                 :            :                           const char *name,
     223                 :            :                           struct lock_class_key *key)
     224                 :            : {
     225   [ #  #  #  # ]:          0 :         BUG_ON(!fn || (unsigned long)fn & ~I915_SW_FENCE_MASK);
     226                 :            : 
     227                 :          0 :         __init_waitqueue_head(&fence->wait, name, key);
     228                 :          0 :         fence->flags = (unsigned long)fn;
     229                 :            : 
     230                 :          0 :         i915_sw_fence_reinit(fence);
     231                 :          0 : }
     232                 :            : 
     233                 :          0 : void i915_sw_fence_reinit(struct i915_sw_fence *fence)
     234                 :            : {
     235                 :          0 :         debug_fence_init(fence);
     236                 :            : 
     237                 :          0 :         atomic_set(&fence->pending, 1);
     238                 :          0 :         fence->error = 0;
     239                 :            : 
     240                 :          0 :         I915_SW_FENCE_BUG_ON(!fence->flags);
     241                 :          0 :         I915_SW_FENCE_BUG_ON(!list_empty(&fence->wait.head));
     242                 :          0 : }
     243                 :            : 
     244                 :          0 : void i915_sw_fence_commit(struct i915_sw_fence *fence)
     245                 :            : {
     246                 :          0 :         debug_fence_activate(fence);
     247                 :          0 :         i915_sw_fence_complete(fence);
     248                 :          0 : }
     249                 :            : 
     250                 :          0 : static int i915_sw_fence_wake(wait_queue_entry_t *wq, unsigned mode, int flags, void *key)
     251                 :            : {
     252                 :          0 :         i915_sw_fence_set_error_once(wq->private, flags);
     253                 :            : 
     254                 :          0 :         list_del(&wq->entry);
     255                 :          0 :         __i915_sw_fence_complete(wq->private, key);
     256                 :            : 
     257         [ #  # ]:          0 :         if (wq->flags & I915_SW_FENCE_FLAG_ALLOC)
     258                 :          0 :                 kfree(wq);
     259                 :          0 :         return 0;
     260                 :            : }
     261                 :            : 
     262                 :            : static bool __i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
     263                 :            :                                     const struct i915_sw_fence * const signaler)
     264                 :            : {
     265                 :            :         wait_queue_entry_t *wq;
     266                 :            : 
     267                 :            :         if (__test_and_set_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
     268                 :            :                 return false;
     269                 :            : 
     270                 :            :         if (fence == signaler)
     271                 :            :                 return true;
     272                 :            : 
     273                 :            :         list_for_each_entry(wq, &fence->wait.head, entry) {
     274                 :            :                 if (wq->func != i915_sw_fence_wake)
     275                 :            :                         continue;
     276                 :            : 
     277                 :            :                 if (__i915_sw_fence_check_if_after(wq->private, signaler))
     278                 :            :                         return true;
     279                 :            :         }
     280                 :            : 
     281                 :            :         return false;
     282                 :            : }
     283                 :            : 
     284                 :            : static void __i915_sw_fence_clear_checked_bit(struct i915_sw_fence *fence)
     285                 :            : {
     286                 :            :         wait_queue_entry_t *wq;
     287                 :            : 
     288                 :            :         if (!__test_and_clear_bit(I915_SW_FENCE_CHECKED_BIT, &fence->flags))
     289                 :            :                 return;
     290                 :            : 
     291                 :            :         list_for_each_entry(wq, &fence->wait.head, entry) {
     292                 :            :                 if (wq->func != i915_sw_fence_wake)
     293                 :            :                         continue;
     294                 :            : 
     295                 :            :                 __i915_sw_fence_clear_checked_bit(wq->private);
     296                 :            :         }
     297                 :            : }
     298                 :            : 
     299                 :          0 : static bool i915_sw_fence_check_if_after(struct i915_sw_fence *fence,
     300                 :            :                                   const struct i915_sw_fence * const signaler)
     301                 :            : {
     302                 :          0 :         unsigned long flags;
     303                 :          0 :         bool err;
     304                 :            : 
     305                 :          0 :         if (!IS_ENABLED(CONFIG_DRM_I915_SW_FENCE_CHECK_DAG))
     306                 :          0 :                 return false;
     307                 :            : 
     308                 :            :         spin_lock_irqsave(&i915_sw_fence_lock, flags);
     309                 :            :         err = __i915_sw_fence_check_if_after(fence, signaler);
     310                 :            :         __i915_sw_fence_clear_checked_bit(fence);
     311                 :            :         spin_unlock_irqrestore(&i915_sw_fence_lock, flags);
     312                 :            : 
     313                 :            :         return err;
     314                 :            : }
     315                 :            : 
     316                 :          0 : static int __i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
     317                 :            :                                           struct i915_sw_fence *signaler,
     318                 :            :                                           wait_queue_entry_t *wq, gfp_t gfp)
     319                 :            : {
     320                 :          0 :         unsigned long flags;
     321                 :          0 :         int pending;
     322                 :            : 
     323                 :          0 :         debug_fence_assert(fence);
     324         [ #  # ]:          0 :         might_sleep_if(gfpflags_allow_blocking(gfp));
     325                 :            : 
     326         [ #  # ]:          0 :         if (i915_sw_fence_done(signaler)) {
     327                 :          0 :                 i915_sw_fence_set_error_once(fence, signaler->error);
     328                 :          0 :                 return 0;
     329                 :            :         }
     330                 :            : 
     331                 :          0 :         debug_fence_assert(signaler);
     332                 :            : 
     333                 :            :         /* The dependency graph must be acyclic. */
     334                 :          0 :         if (unlikely(i915_sw_fence_check_if_after(fence, signaler)))
     335                 :            :                 return -EINVAL;
     336                 :            : 
     337                 :          0 :         pending = 0;
     338         [ #  # ]:          0 :         if (!wq) {
     339         [ #  # ]:          0 :                 wq = kmalloc(sizeof(*wq), gfp);
     340         [ #  # ]:          0 :                 if (!wq) {
     341         [ #  # ]:          0 :                         if (!gfpflags_allow_blocking(gfp))
     342                 :            :                                 return -ENOMEM;
     343                 :            : 
     344                 :          0 :                         i915_sw_fence_wait(signaler);
     345                 :          0 :                         i915_sw_fence_set_error_once(fence, signaler->error);
     346                 :          0 :                         return 0;
     347                 :            :                 }
     348                 :            : 
     349                 :            :                 pending |= I915_SW_FENCE_FLAG_ALLOC;
     350                 :            :         }
     351                 :            : 
     352                 :          0 :         INIT_LIST_HEAD(&wq->entry);
     353                 :          0 :         wq->flags = pending;
     354                 :          0 :         wq->func = i915_sw_fence_wake;
     355                 :          0 :         wq->private = fence;
     356                 :            : 
     357                 :          0 :         i915_sw_fence_await(fence);
     358                 :            : 
     359                 :          0 :         spin_lock_irqsave(&signaler->wait.lock, flags);
     360         [ #  # ]:          0 :         if (likely(!i915_sw_fence_done(signaler))) {
     361                 :          0 :                 __add_wait_queue_entry_tail(&signaler->wait, wq);
     362                 :          0 :                 pending = 1;
     363                 :            :         } else {
     364                 :          0 :                 i915_sw_fence_wake(wq, 0, signaler->error, NULL);
     365                 :          0 :                 pending = 0;
     366                 :            :         }
     367                 :          0 :         spin_unlock_irqrestore(&signaler->wait.lock, flags);
     368                 :            : 
     369                 :          0 :         return pending;
     370                 :            : }
     371                 :            : 
     372                 :          0 : int i915_sw_fence_await_sw_fence(struct i915_sw_fence *fence,
     373                 :            :                                  struct i915_sw_fence *signaler,
     374                 :            :                                  wait_queue_entry_t *wq)
     375                 :            : {
     376                 :          0 :         return __i915_sw_fence_await_sw_fence(fence, signaler, wq, 0);
     377                 :            : }
     378                 :            : 
     379                 :          0 : int i915_sw_fence_await_sw_fence_gfp(struct i915_sw_fence *fence,
     380                 :            :                                      struct i915_sw_fence *signaler,
     381                 :            :                                      gfp_t gfp)
     382                 :            : {
     383                 :          0 :         return __i915_sw_fence_await_sw_fence(fence, signaler, NULL, gfp);
     384                 :            : }
     385                 :            : 
     386                 :            : struct i915_sw_dma_fence_cb_timer {
     387                 :            :         struct i915_sw_dma_fence_cb base;
     388                 :            :         struct dma_fence *dma;
     389                 :            :         struct timer_list timer;
     390                 :            :         struct irq_work work;
     391                 :            :         struct rcu_head rcu;
     392                 :            : };
     393                 :            : 
     394                 :          0 : static void dma_i915_sw_fence_wake(struct dma_fence *dma,
     395                 :            :                                    struct dma_fence_cb *data)
     396                 :            : {
     397                 :          0 :         struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
     398                 :            : 
     399                 :          0 :         i915_sw_fence_set_error_once(cb->fence, dma->error);
     400                 :          0 :         i915_sw_fence_complete(cb->fence);
     401                 :          0 :         kfree(cb);
     402                 :          0 : }
     403                 :            : 
     404                 :          0 : static void timer_i915_sw_fence_wake(struct timer_list *t)
     405                 :            : {
     406                 :          0 :         struct i915_sw_dma_fence_cb_timer *cb = from_timer(cb, t, timer);
     407                 :          0 :         struct i915_sw_fence *fence;
     408                 :            : 
     409                 :          0 :         fence = xchg(&cb->base.fence, NULL);
     410         [ #  # ]:          0 :         if (!fence)
     411                 :            :                 return;
     412                 :            : 
     413                 :          0 :         pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%pS)\n",
     414                 :            :                   cb->dma->ops->get_driver_name(cb->dma),
     415                 :            :                   cb->dma->ops->get_timeline_name(cb->dma),
     416                 :            :                   cb->dma->seqno,
     417                 :            :                   i915_sw_fence_debug_hint(fence));
     418                 :            : 
     419                 :          0 :         i915_sw_fence_set_error_once(fence, -ETIMEDOUT);
     420                 :          0 :         i915_sw_fence_complete(fence);
     421                 :            : }
     422                 :            : 
     423                 :          0 : static void dma_i915_sw_fence_wake_timer(struct dma_fence *dma,
     424                 :            :                                          struct dma_fence_cb *data)
     425                 :            : {
     426                 :          0 :         struct i915_sw_dma_fence_cb_timer *cb =
     427                 :          0 :                 container_of(data, typeof(*cb), base.base);
     428                 :          0 :         struct i915_sw_fence *fence;
     429                 :            : 
     430                 :          0 :         fence = xchg(&cb->base.fence, NULL);
     431         [ #  # ]:          0 :         if (fence) {
     432                 :          0 :                 i915_sw_fence_set_error_once(fence, dma->error);
     433                 :          0 :                 i915_sw_fence_complete(fence);
     434                 :            :         }
     435                 :            : 
     436                 :          0 :         irq_work_queue(&cb->work);
     437                 :          0 : }
     438                 :            : 
     439                 :          0 : static void irq_i915_sw_fence_work(struct irq_work *wrk)
     440                 :            : {
     441                 :          0 :         struct i915_sw_dma_fence_cb_timer *cb =
     442                 :          0 :                 container_of(wrk, typeof(*cb), work);
     443                 :            : 
     444                 :          0 :         del_timer_sync(&cb->timer);
     445                 :          0 :         dma_fence_put(cb->dma);
     446                 :            : 
     447         [ #  # ]:          0 :         kfree_rcu(cb, rcu);
     448                 :          0 : }
     449                 :            : 
     450                 :          0 : int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
     451                 :            :                                   struct dma_fence *dma,
     452                 :            :                                   unsigned long timeout,
     453                 :            :                                   gfp_t gfp)
     454                 :            : {
     455                 :          0 :         struct i915_sw_dma_fence_cb *cb;
     456                 :          0 :         dma_fence_func_t func;
     457                 :          0 :         int ret;
     458                 :            : 
     459                 :          0 :         debug_fence_assert(fence);
     460         [ #  # ]:          0 :         might_sleep_if(gfpflags_allow_blocking(gfp));
     461                 :            : 
     462         [ #  # ]:          0 :         if (dma_fence_is_signaled(dma)) {
     463                 :          0 :                 i915_sw_fence_set_error_once(fence, dma->error);
     464                 :          0 :                 return 0;
     465                 :            :         }
     466                 :            : 
     467         [ #  # ]:          0 :         cb = kmalloc(timeout ?
     468                 :            :                      sizeof(struct i915_sw_dma_fence_cb_timer) :
     469                 :            :                      sizeof(struct i915_sw_dma_fence_cb),
     470                 :            :                      gfp);
     471         [ #  # ]:          0 :         if (!cb) {
     472         [ #  # ]:          0 :                 if (!gfpflags_allow_blocking(gfp))
     473                 :            :                         return -ENOMEM;
     474                 :            : 
     475                 :          0 :                 ret = dma_fence_wait(dma, false);
     476         [ #  # ]:          0 :                 if (ret)
     477                 :            :                         return ret;
     478                 :            : 
     479                 :          0 :                 i915_sw_fence_set_error_once(fence, dma->error);
     480                 :          0 :                 return 0;
     481                 :            :         }
     482                 :            : 
     483                 :          0 :         cb->fence = fence;
     484                 :          0 :         i915_sw_fence_await(fence);
     485                 :            : 
     486                 :          0 :         func = dma_i915_sw_fence_wake;
     487         [ #  # ]:          0 :         if (timeout) {
     488                 :          0 :                 struct i915_sw_dma_fence_cb_timer *timer =
     489                 :          0 :                         container_of(cb, typeof(*timer), base);
     490                 :            : 
     491         [ #  # ]:          0 :                 timer->dma = dma_fence_get(dma);
     492                 :          0 :                 init_irq_work(&timer->work, irq_i915_sw_fence_work);
     493                 :            : 
     494                 :          0 :                 timer_setup(&timer->timer,
     495                 :            :                             timer_i915_sw_fence_wake, TIMER_IRQSAFE);
     496                 :          0 :                 mod_timer(&timer->timer, round_jiffies_up(jiffies + timeout));
     497                 :            : 
     498                 :          0 :                 func = dma_i915_sw_fence_wake_timer;
     499                 :            :         }
     500                 :            : 
     501                 :          0 :         ret = dma_fence_add_callback(dma, &cb->base, func);
     502         [ #  # ]:          0 :         if (ret == 0) {
     503                 :            :                 ret = 1;
     504                 :            :         } else {
     505                 :          0 :                 func(dma, &cb->base);
     506         [ #  # ]:          0 :                 if (ret == -ENOENT) /* fence already signaled */
     507                 :          0 :                         ret = 0;
     508                 :            :         }
     509                 :            : 
     510                 :            :         return ret;
     511                 :            : }
     512                 :            : 
     513                 :          0 : static void __dma_i915_sw_fence_wake(struct dma_fence *dma,
     514                 :            :                                      struct dma_fence_cb *data)
     515                 :            : {
     516                 :          0 :         struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base);
     517                 :            : 
     518                 :          0 :         i915_sw_fence_set_error_once(cb->fence, dma->error);
     519                 :          0 :         i915_sw_fence_complete(cb->fence);
     520                 :          0 : }
     521                 :            : 
     522                 :          0 : int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
     523                 :            :                                     struct dma_fence *dma,
     524                 :            :                                     struct i915_sw_dma_fence_cb *cb)
     525                 :            : {
     526                 :          0 :         int ret;
     527                 :            : 
     528                 :          0 :         debug_fence_assert(fence);
     529                 :            : 
     530         [ #  # ]:          0 :         if (dma_fence_is_signaled(dma)) {
     531                 :          0 :                 i915_sw_fence_set_error_once(fence, dma->error);
     532                 :          0 :                 return 0;
     533                 :            :         }
     534                 :            : 
     535                 :          0 :         cb->fence = fence;
     536                 :          0 :         i915_sw_fence_await(fence);
     537                 :            : 
     538                 :          0 :         ret = dma_fence_add_callback(dma, &cb->base, __dma_i915_sw_fence_wake);
     539         [ #  # ]:          0 :         if (ret == 0) {
     540                 :            :                 ret = 1;
     541                 :            :         } else {
     542                 :          0 :                 __dma_i915_sw_fence_wake(dma, &cb->base);
     543         [ #  # ]:          0 :                 if (ret == -ENOENT) /* fence already signaled */
     544                 :          0 :                         ret = 0;
     545                 :            :         }
     546                 :            : 
     547                 :            :         return ret;
     548                 :            : }
     549                 :            : 
     550                 :          0 : int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
     551                 :            :                                     struct dma_resv *resv,
     552                 :            :                                     const struct dma_fence_ops *exclude,
     553                 :            :                                     bool write,
     554                 :            :                                     unsigned long timeout,
     555                 :            :                                     gfp_t gfp)
     556                 :            : {
     557                 :          0 :         struct dma_fence *excl;
     558                 :          0 :         int ret = 0, pending;
     559                 :            : 
     560                 :          0 :         debug_fence_assert(fence);
     561         [ #  # ]:          0 :         might_sleep_if(gfpflags_allow_blocking(gfp));
     562                 :            : 
     563         [ #  # ]:          0 :         if (write) {
     564                 :          0 :                 struct dma_fence **shared;
     565                 :          0 :                 unsigned int count, i;
     566                 :            : 
     567                 :          0 :                 ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared);
     568         [ #  # ]:          0 :                 if (ret)
     569                 :          0 :                         return ret;
     570                 :            : 
     571         [ #  # ]:          0 :                 for (i = 0; i < count; i++) {
     572         [ #  # ]:          0 :                         if (shared[i]->ops == exclude)
     573                 :          0 :                                 continue;
     574                 :            : 
     575                 :          0 :                         pending = i915_sw_fence_await_dma_fence(fence,
     576                 :            :                                                                 shared[i],
     577                 :            :                                                                 timeout,
     578                 :            :                                                                 gfp);
     579         [ #  # ]:          0 :                         if (pending < 0) {
     580                 :            :                                 ret = pending;
     581                 :            :                                 break;
     582                 :            :                         }
     583                 :            : 
     584                 :          0 :                         ret |= pending;
     585                 :            :                 }
     586                 :            : 
     587         [ #  # ]:          0 :                 for (i = 0; i < count; i++)
     588                 :          0 :                         dma_fence_put(shared[i]);
     589                 :          0 :                 kfree(shared);
     590                 :            :         } else {
     591         [ #  # ]:          0 :                 excl = dma_resv_get_excl_rcu(resv);
     592                 :            :         }
     593                 :            : 
     594   [ #  #  #  #  :          0 :         if (ret >= 0 && excl && excl->ops != exclude) {
                   #  # ]
     595                 :          0 :                 pending = i915_sw_fence_await_dma_fence(fence,
     596                 :            :                                                         excl,
     597                 :            :                                                         timeout,
     598                 :            :                                                         gfp);
     599         [ #  # ]:          0 :                 if (pending < 0)
     600                 :            :                         ret = pending;
     601                 :            :                 else
     602                 :          0 :                         ret |= pending;
     603                 :            :         }
     604                 :            : 
     605                 :          0 :         dma_fence_put(excl);
     606                 :            : 
     607                 :          0 :         return ret;
     608                 :            : }
     609                 :            : 
     610                 :            : #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
     611                 :            : #include "selftests/lib_sw_fence.c"
     612                 :            : #include "selftests/i915_sw_fence.c"
     613                 :            : #endif

Generated by: LCOV version 1.14