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

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * SPDX-License-Identifier: MIT
       3                 :            :  *
       4                 :            :  * Copyright © 2019 Intel Corporation
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "gem/i915_gem_object.h"
       8                 :            : #include "i915_drv.h"
       9                 :            : #include "i915_vma.h"
      10                 :            : #include "intel_engine.h"
      11                 :            : #include "intel_ring.h"
      12                 :            : #include "intel_timeline.h"
      13                 :            : 
      14                 :          0 : unsigned int intel_ring_update_space(struct intel_ring *ring)
      15                 :            : {
      16                 :          0 :         unsigned int space;
      17                 :            : 
      18                 :          0 :         space = __intel_ring_space(ring->head, ring->emit, ring->size);
      19                 :            : 
      20                 :          0 :         ring->space = space;
      21         [ #  # ]:          0 :         return space;
      22                 :            : }
      23                 :            : 
      24                 :          0 : int intel_ring_pin(struct intel_ring *ring)
      25                 :            : {
      26                 :          0 :         struct i915_vma *vma = ring->vma;
      27                 :          0 :         unsigned int flags;
      28                 :          0 :         void *addr;
      29                 :          0 :         int ret;
      30                 :            : 
      31         [ #  # ]:          0 :         if (atomic_fetch_inc(&ring->pin_count))
      32                 :            :                 return 0;
      33                 :            : 
      34                 :          0 :         flags = PIN_GLOBAL;
      35                 :            : 
      36                 :            :         /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
      37         [ #  # ]:          0 :         flags |= PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma);
      38                 :            : 
      39         [ #  # ]:          0 :         if (vma->obj->stolen)
      40                 :          0 :                 flags |= PIN_MAPPABLE;
      41                 :            :         else
      42                 :          0 :                 flags |= PIN_HIGH;
      43                 :            : 
      44                 :          0 :         ret = i915_vma_pin(vma, 0, 0, flags);
      45         [ #  # ]:          0 :         if (unlikely(ret))
      46                 :          0 :                 goto err_unpin;
      47                 :            : 
      48         [ #  # ]:          0 :         if (i915_vma_is_map_and_fenceable(vma))
      49                 :          0 :                 addr = (void __force *)i915_vma_pin_iomap(vma);
      50                 :            :         else
      51                 :          0 :                 addr = i915_gem_object_pin_map(vma->obj,
      52                 :          0 :                                                i915_coherent_map_type(vma->vm->i915));
      53         [ #  # ]:          0 :         if (IS_ERR(addr)) {
      54                 :          0 :                 ret = PTR_ERR(addr);
      55                 :          0 :                 goto err_ring;
      56                 :            :         }
      57                 :            : 
      58                 :          0 :         i915_vma_make_unshrinkable(vma);
      59                 :            : 
      60                 :            :         /* Discard any unused bytes beyond that submitted to hw. */
      61                 :          0 :         intel_ring_reset(ring, ring->emit);
      62                 :            : 
      63                 :          0 :         ring->vaddr = addr;
      64                 :          0 :         return 0;
      65                 :            : 
      66                 :            : err_ring:
      67                 :          0 :         i915_vma_unpin(vma);
      68                 :          0 : err_unpin:
      69                 :          0 :         atomic_dec(&ring->pin_count);
      70                 :          0 :         return ret;
      71                 :            : }
      72                 :            : 
      73                 :          0 : void intel_ring_reset(struct intel_ring *ring, u32 tail)
      74                 :            : {
      75                 :          0 :         tail = intel_ring_wrap(ring, tail);
      76                 :          0 :         ring->tail = tail;
      77                 :          0 :         ring->head = tail;
      78                 :          0 :         ring->emit = tail;
      79                 :          0 :         intel_ring_update_space(ring);
      80                 :          0 : }
      81                 :            : 
      82                 :          0 : void intel_ring_unpin(struct intel_ring *ring)
      83                 :            : {
      84                 :          0 :         struct i915_vma *vma = ring->vma;
      85                 :            : 
      86         [ #  # ]:          0 :         if (!atomic_dec_and_test(&ring->pin_count))
      87                 :            :                 return;
      88                 :            : 
      89                 :          0 :         i915_vma_unset_ggtt_write(vma);
      90         [ #  # ]:          0 :         if (i915_vma_is_map_and_fenceable(vma))
      91                 :          0 :                 i915_vma_unpin_iomap(vma);
      92                 :            :         else
      93                 :          0 :                 i915_gem_object_unpin_map(vma->obj);
      94                 :            : 
      95                 :          0 :         i915_vma_make_purgeable(vma);
      96                 :          0 :         i915_vma_unpin(vma);
      97                 :            : }
      98                 :            : 
      99                 :          0 : static struct i915_vma *create_ring_vma(struct i915_ggtt *ggtt, int size)
     100                 :            : {
     101                 :          0 :         struct i915_address_space *vm = &ggtt->vm;
     102                 :          0 :         struct drm_i915_private *i915 = vm->i915;
     103                 :          0 :         struct drm_i915_gem_object *obj;
     104                 :          0 :         struct i915_vma *vma;
     105                 :            : 
     106         [ #  # ]:          0 :         obj = ERR_PTR(-ENODEV);
     107         [ #  # ]:          0 :         if (i915_ggtt_has_aperture(ggtt))
     108                 :          0 :                 obj = i915_gem_object_create_stolen(i915, size);
     109         [ #  # ]:          0 :         if (IS_ERR(obj))
     110                 :          0 :                 obj = i915_gem_object_create_internal(i915, size);
     111         [ #  # ]:          0 :         if (IS_ERR(obj))
     112                 :            :                 return ERR_CAST(obj);
     113                 :            : 
     114                 :            :         /*
     115                 :            :          * Mark ring buffers as read-only from GPU side (so no stray overwrites)
     116                 :            :          * if supported by the platform's GGTT.
     117                 :            :          */
     118         [ #  # ]:          0 :         if (vm->has_read_only)
     119                 :          0 :                 i915_gem_object_set_readonly(obj);
     120                 :            : 
     121                 :          0 :         vma = i915_vma_instance(obj, vm, NULL);
     122         [ #  # ]:          0 :         if (IS_ERR(vma))
     123                 :          0 :                 goto err;
     124                 :            : 
     125                 :            :         return vma;
     126                 :            : 
     127                 :            : err:
     128                 :          0 :         i915_gem_object_put(obj);
     129                 :          0 :         return vma;
     130                 :            : }
     131                 :            : 
     132                 :            : struct intel_ring *
     133                 :          0 : intel_engine_create_ring(struct intel_engine_cs *engine, int size)
     134                 :            : {
     135                 :          0 :         struct drm_i915_private *i915 = engine->i915;
     136                 :          0 :         struct intel_ring *ring;
     137                 :          0 :         struct i915_vma *vma;
     138                 :            : 
     139                 :          0 :         GEM_BUG_ON(!is_power_of_2(size));
     140                 :          0 :         GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES);
     141                 :            : 
     142                 :          0 :         ring = kzalloc(sizeof(*ring), GFP_KERNEL);
     143         [ #  # ]:          0 :         if (!ring)
     144                 :            :                 return ERR_PTR(-ENOMEM);
     145                 :            : 
     146                 :          0 :         kref_init(&ring->ref);
     147                 :          0 :         ring->size = size;
     148   [ #  #  #  #  :          0 :         ring->wrap = BITS_PER_TYPE(ring->size) - ilog2(size);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     149                 :            : 
     150                 :            :         /*
     151                 :            :          * Workaround an erratum on the i830 which causes a hang if
     152                 :            :          * the TAIL pointer points to within the last 2 cachelines
     153                 :            :          * of the buffer.
     154                 :            :          */
     155                 :          0 :         ring->effective_size = size;
     156   [ #  #  #  # ]:          0 :         if (IS_I830(i915) || IS_I845G(i915))
     157                 :          0 :                 ring->effective_size -= 2 * CACHELINE_BYTES;
     158                 :            : 
     159                 :          0 :         intel_ring_update_space(ring);
     160                 :            : 
     161                 :          0 :         vma = create_ring_vma(engine->gt->ggtt, size);
     162         [ #  # ]:          0 :         if (IS_ERR(vma)) {
     163                 :          0 :                 kfree(ring);
     164                 :          0 :                 return ERR_CAST(vma);
     165                 :            :         }
     166                 :          0 :         ring->vma = vma;
     167                 :            : 
     168                 :          0 :         return ring;
     169                 :            : }
     170                 :            : 
     171                 :          0 : void intel_ring_free(struct kref *ref)
     172                 :            : {
     173                 :          0 :         struct intel_ring *ring = container_of(ref, typeof(*ring), ref);
     174                 :            : 
     175                 :          0 :         i915_vma_put(ring->vma);
     176                 :          0 :         kfree(ring);
     177                 :          0 : }
     178                 :            : 
     179                 :            : static noinline int
     180                 :          0 : wait_for_space(struct intel_ring *ring,
     181                 :            :                struct intel_timeline *tl,
     182                 :            :                unsigned int bytes)
     183                 :            : {
     184                 :          0 :         struct i915_request *target;
     185                 :          0 :         long timeout;
     186                 :            : 
     187         [ #  # ]:          0 :         if (intel_ring_update_space(ring) >= bytes)
     188                 :            :                 return 0;
     189                 :            : 
     190                 :          0 :         GEM_BUG_ON(list_empty(&tl->requests));
     191         [ #  # ]:          0 :         list_for_each_entry(target, &tl->requests, link) {
     192         [ #  # ]:          0 :                 if (target->ring != ring)
     193                 :          0 :                         continue;
     194                 :            : 
     195                 :            :                 /* Would completion of this request free enough space? */
     196         [ #  # ]:          0 :                 if (bytes <= __intel_ring_space(target->postfix,
     197                 :            :                                                 ring->emit, ring->size))
     198                 :            :                         break;
     199                 :            :         }
     200                 :            : 
     201         [ #  # ]:          0 :         if (GEM_WARN_ON(&target->link == &tl->requests))
     202                 :            :                 return -ENOSPC;
     203                 :            : 
     204                 :          0 :         timeout = i915_request_wait(target,
     205                 :            :                                     I915_WAIT_INTERRUPTIBLE,
     206                 :            :                                     MAX_SCHEDULE_TIMEOUT);
     207         [ #  # ]:          0 :         if (timeout < 0)
     208                 :          0 :                 return timeout;
     209                 :            : 
     210                 :          0 :         i915_request_retire_upto(target);
     211                 :            : 
     212                 :          0 :         intel_ring_update_space(ring);
     213                 :          0 :         GEM_BUG_ON(ring->space < bytes);
     214                 :          0 :         return 0;
     215                 :            : }
     216                 :            : 
     217                 :          0 : u32 *intel_ring_begin(struct i915_request *rq, unsigned int num_dwords)
     218                 :            : {
     219                 :          0 :         struct intel_ring *ring = rq->ring;
     220                 :          0 :         const unsigned int remain_usable = ring->effective_size - ring->emit;
     221                 :          0 :         const unsigned int bytes = num_dwords * sizeof(u32);
     222                 :          0 :         unsigned int need_wrap = 0;
     223                 :          0 :         unsigned int total_bytes;
     224                 :          0 :         u32 *cs;
     225                 :            : 
     226                 :            :         /* Packets must be qword aligned. */
     227                 :          0 :         GEM_BUG_ON(num_dwords & 1);
     228                 :            : 
     229                 :          0 :         total_bytes = bytes + rq->reserved_space;
     230                 :          0 :         GEM_BUG_ON(total_bytes > ring->effective_size);
     231                 :            : 
     232         [ #  # ]:          0 :         if (unlikely(total_bytes > remain_usable)) {
     233                 :          0 :                 const int remain_actual = ring->size - ring->emit;
     234                 :            : 
     235         [ #  # ]:          0 :                 if (bytes > remain_usable) {
     236                 :            :                         /*
     237                 :            :                          * Not enough space for the basic request. So need to
     238                 :            :                          * flush out the remainder and then wait for
     239                 :            :                          * base + reserved.
     240                 :            :                          */
     241                 :          0 :                         total_bytes += remain_actual;
     242                 :          0 :                         need_wrap = remain_actual | 1;
     243                 :            :                 } else  {
     244                 :            :                         /*
     245                 :            :                          * The base request will fit but the reserved space
     246                 :            :                          * falls off the end. So we don't need an immediate
     247                 :            :                          * wrap and only need to effectively wait for the
     248                 :            :                          * reserved size from the start of ringbuffer.
     249                 :            :                          */
     250                 :          0 :                         total_bytes = rq->reserved_space + remain_actual;
     251                 :            :                 }
     252                 :            :         }
     253                 :            : 
     254         [ #  # ]:          0 :         if (unlikely(total_bytes > ring->space)) {
     255                 :          0 :                 int ret;
     256                 :            : 
     257                 :            :                 /*
     258                 :            :                  * Space is reserved in the ringbuffer for finalising the
     259                 :            :                  * request, as that cannot be allowed to fail. During request
     260                 :            :                  * finalisation, reserved_space is set to 0 to stop the
     261                 :            :                  * overallocation and the assumption is that then we never need
     262                 :            :                  * to wait (which has the risk of failing with EINTR).
     263                 :            :                  *
     264                 :            :                  * See also i915_request_alloc() and i915_request_add().
     265                 :            :                  */
     266                 :          0 :                 GEM_BUG_ON(!rq->reserved_space);
     267                 :            : 
     268                 :          0 :                 ret = wait_for_space(ring,
     269                 :            :                                      i915_request_timeline(rq),
     270                 :            :                                      total_bytes);
     271         [ #  # ]:          0 :                 if (unlikely(ret))
     272                 :          0 :                         return ERR_PTR(ret);
     273                 :            :         }
     274                 :            : 
     275         [ #  # ]:          0 :         if (unlikely(need_wrap)) {
     276                 :          0 :                 need_wrap &= ~1;
     277                 :          0 :                 GEM_BUG_ON(need_wrap > ring->space);
     278                 :          0 :                 GEM_BUG_ON(ring->emit + need_wrap > ring->size);
     279                 :          0 :                 GEM_BUG_ON(!IS_ALIGNED(need_wrap, sizeof(u64)));
     280                 :            : 
     281                 :            :                 /* Fill the tail with MI_NOOP */
     282                 :          0 :                 memset64(ring->vaddr + ring->emit, 0, need_wrap / sizeof(u64));
     283                 :          0 :                 ring->space -= need_wrap;
     284                 :          0 :                 ring->emit = 0;
     285                 :            :         }
     286                 :            : 
     287                 :          0 :         GEM_BUG_ON(ring->emit > ring->size - bytes);
     288                 :          0 :         GEM_BUG_ON(ring->space < bytes);
     289                 :          0 :         cs = ring->vaddr + ring->emit;
     290                 :          0 :         GEM_DEBUG_EXEC(memset32(cs, POISON_INUSE, bytes / sizeof(*cs)));
     291                 :          0 :         ring->emit += bytes;
     292                 :          0 :         ring->space -= bytes;
     293                 :            : 
     294                 :          0 :         return cs;
     295                 :            : }
     296                 :            : 
     297                 :            : /* Align the ring tail to a cacheline boundary */
     298                 :          0 : int intel_ring_cacheline_align(struct i915_request *rq)
     299                 :            : {
     300                 :          0 :         int num_dwords;
     301                 :          0 :         void *cs;
     302                 :            : 
     303                 :          0 :         num_dwords = (rq->ring->emit & (CACHELINE_BYTES - 1)) / sizeof(u32);
     304         [ #  # ]:          0 :         if (num_dwords == 0)
     305                 :            :                 return 0;
     306                 :            : 
     307                 :          0 :         num_dwords = CACHELINE_DWORDS - num_dwords;
     308                 :          0 :         GEM_BUG_ON(num_dwords & 1);
     309                 :            : 
     310                 :          0 :         cs = intel_ring_begin(rq, num_dwords);
     311         [ #  # ]:          0 :         if (IS_ERR(cs))
     312                 :          0 :                 return PTR_ERR(cs);
     313                 :            : 
     314                 :          0 :         memset64(cs, (u64)MI_NOOP << 32 | MI_NOOP, num_dwords / 2);
     315                 :          0 :         intel_ring_advance(rq, cs + num_dwords);
     316                 :            : 
     317                 :          0 :         GEM_BUG_ON(rq->ring->emit & (CACHELINE_BYTES - 1));
     318                 :          0 :         return 0;
     319                 :            : }

Generated by: LCOV version 1.14