LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915/display - intel_frontbuffer.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 109 0.0 %
Date: 2022-03-28 13:20:08 Functions: 0 12 0.0 %
Branches: 0 34 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright © 2014 Intel Corporation
       3                 :            :  *
       4                 :            :  * Permission is hereby granted, free of charge, to any person obtaining a
       5                 :            :  * copy of this software and associated documentation files (the "Software"),
       6                 :            :  * to deal in the Software without restriction, including without limitation
       7                 :            :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8                 :            :  * and/or sell copies of the Software, and to permit persons to whom the
       9                 :            :  * Software is furnished to do so, subject to the following conditions:
      10                 :            :  *
      11                 :            :  * The above copyright notice and this permission notice (including the next
      12                 :            :  * paragraph) shall be included in all copies or substantial portions of the
      13                 :            :  * Software.
      14                 :            :  *
      15                 :            :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16                 :            :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17                 :            :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18                 :            :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19                 :            :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20                 :            :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      21                 :            :  * DEALINGS IN THE SOFTWARE.
      22                 :            :  *
      23                 :            :  * Authors:
      24                 :            :  *      Daniel Vetter <daniel.vetter@ffwll.ch>
      25                 :            :  */
      26                 :            : 
      27                 :            : /**
      28                 :            :  * DOC: frontbuffer tracking
      29                 :            :  *
      30                 :            :  * Many features require us to track changes to the currently active
      31                 :            :  * frontbuffer, especially rendering targeted at the frontbuffer.
      32                 :            :  *
      33                 :            :  * To be able to do so we track frontbuffers using a bitmask for all possible
      34                 :            :  * frontbuffer slots through intel_frontbuffer_track(). The functions in this
      35                 :            :  * file are then called when the contents of the frontbuffer are invalidated,
      36                 :            :  * when frontbuffer rendering has stopped again to flush out all the changes
      37                 :            :  * and when the frontbuffer is exchanged with a flip. Subsystems interested in
      38                 :            :  * frontbuffer changes (e.g. PSR, FBC, DRRS) should directly put their callbacks
      39                 :            :  * into the relevant places and filter for the frontbuffer slots that they are
      40                 :            :  * interested int.
      41                 :            :  *
      42                 :            :  * On a high level there are two types of powersaving features. The first one
      43                 :            :  * work like a special cache (FBC and PSR) and are interested when they should
      44                 :            :  * stop caching and when to restart caching. This is done by placing callbacks
      45                 :            :  * into the invalidate and the flush functions: At invalidate the caching must
      46                 :            :  * be stopped and at flush time it can be restarted. And maybe they need to know
      47                 :            :  * when the frontbuffer changes (e.g. when the hw doesn't initiate an invalidate
      48                 :            :  * and flush on its own) which can be achieved with placing callbacks into the
      49                 :            :  * flip functions.
      50                 :            :  *
      51                 :            :  * The other type of display power saving feature only cares about busyness
      52                 :            :  * (e.g. DRRS). In that case all three (invalidate, flush and flip) indicate
      53                 :            :  * busyness. There is no direct way to detect idleness. Instead an idle timer
      54                 :            :  * work delayed work should be started from the flush and flip functions and
      55                 :            :  * cancelled as soon as busyness is detected.
      56                 :            :  */
      57                 :            : 
      58                 :            : #include "display/intel_dp.h"
      59                 :            : 
      60                 :            : #include "i915_drv.h"
      61                 :            : #include "intel_display_types.h"
      62                 :            : #include "intel_fbc.h"
      63                 :            : #include "intel_frontbuffer.h"
      64                 :            : #include "intel_psr.h"
      65                 :            : 
      66                 :            : /**
      67                 :            :  * frontbuffer_flush - flush frontbuffer
      68                 :            :  * @i915: i915 device
      69                 :            :  * @frontbuffer_bits: frontbuffer plane tracking bits
      70                 :            :  * @origin: which operation caused the flush
      71                 :            :  *
      72                 :            :  * This function gets called every time rendering on the given planes has
      73                 :            :  * completed and frontbuffer caching can be started again. Flushes will get
      74                 :            :  * delayed if they're blocked by some outstanding asynchronous rendering.
      75                 :            :  *
      76                 :            :  * Can be called without any locks held.
      77                 :            :  */
      78                 :          0 : static void frontbuffer_flush(struct drm_i915_private *i915,
      79                 :            :                               unsigned int frontbuffer_bits,
      80                 :            :                               enum fb_op_origin origin)
      81                 :            : {
      82                 :            :         /* Delay flushing when rings are still busy.*/
      83                 :          0 :         spin_lock(&i915->fb_tracking.lock);
      84                 :          0 :         frontbuffer_bits &= ~i915->fb_tracking.busy_bits;
      85                 :          0 :         spin_unlock(&i915->fb_tracking.lock);
      86                 :            : 
      87         [ #  # ]:          0 :         if (!frontbuffer_bits)
      88                 :            :                 return;
      89                 :            : 
      90                 :          0 :         might_sleep();
      91                 :          0 :         intel_edp_drrs_flush(i915, frontbuffer_bits);
      92                 :          0 :         intel_psr_flush(i915, frontbuffer_bits, origin);
      93                 :          0 :         intel_fbc_flush(i915, frontbuffer_bits, origin);
      94                 :            : }
      95                 :            : 
      96                 :            : /**
      97                 :            :  * intel_frontbuffer_flip_prepare - prepare asynchronous frontbuffer flip
      98                 :            :  * @i915: i915 device
      99                 :            :  * @frontbuffer_bits: frontbuffer plane tracking bits
     100                 :            :  *
     101                 :            :  * This function gets called after scheduling a flip on @obj. The actual
     102                 :            :  * frontbuffer flushing will be delayed until completion is signalled with
     103                 :            :  * intel_frontbuffer_flip_complete. If an invalidate happens in between this
     104                 :            :  * flush will be cancelled.
     105                 :            :  *
     106                 :            :  * Can be called without any locks held.
     107                 :            :  */
     108                 :          0 : void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
     109                 :            :                                     unsigned frontbuffer_bits)
     110                 :            : {
     111                 :          0 :         spin_lock(&i915->fb_tracking.lock);
     112                 :          0 :         i915->fb_tracking.flip_bits |= frontbuffer_bits;
     113                 :            :         /* Remove stale busy bits due to the old buffer. */
     114                 :          0 :         i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
     115                 :          0 :         spin_unlock(&i915->fb_tracking.lock);
     116                 :          0 : }
     117                 :            : 
     118                 :            : /**
     119                 :            :  * intel_frontbuffer_flip_complete - complete asynchronous frontbuffer flip
     120                 :            :  * @i915: i915 device
     121                 :            :  * @frontbuffer_bits: frontbuffer plane tracking bits
     122                 :            :  *
     123                 :            :  * This function gets called after the flip has been latched and will complete
     124                 :            :  * on the next vblank. It will execute the flush if it hasn't been cancelled yet.
     125                 :            :  *
     126                 :            :  * Can be called without any locks held.
     127                 :            :  */
     128                 :          0 : void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
     129                 :            :                                      unsigned frontbuffer_bits)
     130                 :            : {
     131                 :          0 :         spin_lock(&i915->fb_tracking.lock);
     132                 :            :         /* Mask any cancelled flips. */
     133                 :          0 :         frontbuffer_bits &= i915->fb_tracking.flip_bits;
     134                 :          0 :         i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
     135                 :          0 :         spin_unlock(&i915->fb_tracking.lock);
     136                 :            : 
     137         [ #  # ]:          0 :         if (frontbuffer_bits)
     138                 :          0 :                 frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
     139                 :          0 : }
     140                 :            : 
     141                 :            : /**
     142                 :            :  * intel_frontbuffer_flip - synchronous frontbuffer flip
     143                 :            :  * @i915: i915 device
     144                 :            :  * @frontbuffer_bits: frontbuffer plane tracking bits
     145                 :            :  *
     146                 :            :  * This function gets called after scheduling a flip on @obj. This is for
     147                 :            :  * synchronous plane updates which will happen on the next vblank and which will
     148                 :            :  * not get delayed by pending gpu rendering.
     149                 :            :  *
     150                 :            :  * Can be called without any locks held.
     151                 :            :  */
     152                 :          0 : void intel_frontbuffer_flip(struct drm_i915_private *i915,
     153                 :            :                             unsigned frontbuffer_bits)
     154                 :            : {
     155                 :          0 :         spin_lock(&i915->fb_tracking.lock);
     156                 :            :         /* Remove stale busy bits due to the old buffer. */
     157                 :          0 :         i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
     158                 :          0 :         spin_unlock(&i915->fb_tracking.lock);
     159                 :            : 
     160                 :          0 :         frontbuffer_flush(i915, frontbuffer_bits, ORIGIN_FLIP);
     161                 :          0 : }
     162                 :            : 
     163                 :          0 : void __intel_fb_invalidate(struct intel_frontbuffer *front,
     164                 :            :                            enum fb_op_origin origin,
     165                 :            :                            unsigned int frontbuffer_bits)
     166                 :            : {
     167         [ #  # ]:          0 :         struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
     168                 :            : 
     169         [ #  # ]:          0 :         if (origin == ORIGIN_CS) {
     170                 :          0 :                 spin_lock(&i915->fb_tracking.lock);
     171                 :          0 :                 i915->fb_tracking.busy_bits |= frontbuffer_bits;
     172                 :          0 :                 i915->fb_tracking.flip_bits &= ~frontbuffer_bits;
     173                 :          0 :                 spin_unlock(&i915->fb_tracking.lock);
     174                 :            :         }
     175                 :            : 
     176                 :          0 :         might_sleep();
     177                 :          0 :         intel_psr_invalidate(i915, frontbuffer_bits, origin);
     178                 :          0 :         intel_edp_drrs_invalidate(i915, frontbuffer_bits);
     179                 :          0 :         intel_fbc_invalidate(i915, frontbuffer_bits, origin);
     180                 :          0 : }
     181                 :            : 
     182                 :          0 : void __intel_fb_flush(struct intel_frontbuffer *front,
     183                 :            :                       enum fb_op_origin origin,
     184                 :            :                       unsigned int frontbuffer_bits)
     185                 :            : {
     186         [ #  # ]:          0 :         struct drm_i915_private *i915 = to_i915(front->obj->base.dev);
     187                 :            : 
     188         [ #  # ]:          0 :         if (origin == ORIGIN_CS) {
     189                 :          0 :                 spin_lock(&i915->fb_tracking.lock);
     190                 :            :                 /* Filter out new bits since rendering started. */
     191                 :          0 :                 frontbuffer_bits &= i915->fb_tracking.busy_bits;
     192                 :          0 :                 i915->fb_tracking.busy_bits &= ~frontbuffer_bits;
     193                 :          0 :                 spin_unlock(&i915->fb_tracking.lock);
     194                 :            :         }
     195                 :            : 
     196         [ #  # ]:          0 :         if (frontbuffer_bits)
     197                 :          0 :                 frontbuffer_flush(i915, frontbuffer_bits, origin);
     198                 :          0 : }
     199                 :            : 
     200                 :          0 : static int frontbuffer_active(struct i915_active *ref)
     201                 :            : {
     202                 :          0 :         struct intel_frontbuffer *front =
     203                 :          0 :                 container_of(ref, typeof(*front), write);
     204                 :            : 
     205                 :          0 :         kref_get(&front->ref);
     206                 :          0 :         return 0;
     207                 :            : }
     208                 :            : 
     209                 :            : __i915_active_call
     210                 :          0 : static void frontbuffer_retire(struct i915_active *ref)
     211                 :            : {
     212                 :          0 :         struct intel_frontbuffer *front =
     213                 :          0 :                 container_of(ref, typeof(*front), write);
     214                 :            : 
     215                 :          0 :         intel_frontbuffer_flush(front, ORIGIN_CS);
     216                 :          0 :         intel_frontbuffer_put(front);
     217                 :          0 : }
     218                 :            : 
     219                 :          0 : static void frontbuffer_release(struct kref *ref)
     220                 :            :         __releases(&to_i915(front->obj->base.dev)->fb_tracking.lock)
     221                 :            : {
     222                 :          0 :         struct intel_frontbuffer *front =
     223                 :          0 :                 container_of(ref, typeof(*front), ref);
     224                 :          0 :         struct drm_i915_gem_object *obj = front->obj;
     225                 :          0 :         struct i915_vma *vma;
     226                 :            : 
     227                 :          0 :         spin_lock(&obj->vma.lock);
     228   [ #  #  #  # ]:          0 :         for_each_ggtt_vma(vma, obj)
     229                 :          0 :                 vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
     230                 :          0 :         spin_unlock(&obj->vma.lock);
     231                 :            : 
     232                 :          0 :         RCU_INIT_POINTER(obj->frontbuffer, NULL);
     233                 :          0 :         spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock);
     234                 :            : 
     235                 :          0 :         i915_gem_object_put(obj);
     236         [ #  # ]:          0 :         kfree_rcu(front, rcu);
     237                 :          0 : }
     238                 :            : 
     239                 :            : struct intel_frontbuffer *
     240                 :          0 : intel_frontbuffer_get(struct drm_i915_gem_object *obj)
     241                 :            : {
     242                 :          0 :         struct drm_i915_private *i915 = to_i915(obj->base.dev);
     243                 :          0 :         struct intel_frontbuffer *front;
     244                 :            : 
     245                 :          0 :         front = __intel_frontbuffer_get(obj);
     246         [ #  # ]:          0 :         if (front)
     247                 :            :                 return front;
     248                 :            : 
     249                 :          0 :         front = kmalloc(sizeof(*front), GFP_KERNEL);
     250         [ #  # ]:          0 :         if (!front)
     251                 :            :                 return NULL;
     252                 :            : 
     253                 :          0 :         front->obj = obj;
     254                 :          0 :         kref_init(&front->ref);
     255                 :          0 :         atomic_set(&front->bits, 0);
     256                 :          0 :         i915_active_init(&front->write,
     257                 :            :                          frontbuffer_active,
     258                 :            :                          i915_active_may_sleep(frontbuffer_retire));
     259                 :            : 
     260                 :          0 :         spin_lock(&i915->fb_tracking.lock);
     261         [ #  # ]:          0 :         if (rcu_access_pointer(obj->frontbuffer)) {
     262                 :          0 :                 kfree(front);
     263                 :          0 :                 front = rcu_dereference_protected(obj->frontbuffer, true);
     264                 :          0 :                 kref_get(&front->ref);
     265                 :            :         } else {
     266                 :          0 :                 i915_gem_object_get(obj);
     267                 :          0 :                 rcu_assign_pointer(obj->frontbuffer, front);
     268                 :            :         }
     269                 :          0 :         spin_unlock(&i915->fb_tracking.lock);
     270                 :            : 
     271                 :          0 :         return front;
     272                 :            : }
     273                 :            : 
     274                 :          0 : void intel_frontbuffer_put(struct intel_frontbuffer *front)
     275                 :            : {
     276                 :          0 :         kref_put_lock(&front->ref,
     277                 :            :                       frontbuffer_release,
     278                 :          0 :                       &to_i915(front->obj->base.dev)->fb_tracking.lock);
     279                 :          0 : }
     280                 :            : 
     281                 :            : /**
     282                 :            :  * intel_frontbuffer_track - update frontbuffer tracking
     283                 :            :  * @old: current buffer for the frontbuffer slots
     284                 :            :  * @new: new buffer for the frontbuffer slots
     285                 :            :  * @frontbuffer_bits: bitmask of frontbuffer slots
     286                 :            :  *
     287                 :            :  * This updates the frontbuffer tracking bits @frontbuffer_bits by clearing them
     288                 :            :  * from @old and setting them in @new. Both @old and @new can be NULL.
     289                 :            :  */
     290                 :          0 : void intel_frontbuffer_track(struct intel_frontbuffer *old,
     291                 :            :                              struct intel_frontbuffer *new,
     292                 :            :                              unsigned int frontbuffer_bits)
     293                 :            : {
     294                 :            :         /*
     295                 :            :          * Control of individual bits within the mask are guarded by
     296                 :            :          * the owning plane->mutex, i.e. we can never see concurrent
     297                 :            :          * manipulation of individual bits. But since the bitfield as a whole
     298                 :            :          * is updated using RMW, we need to use atomics in order to update
     299                 :            :          * the bits.
     300                 :            :          */
     301                 :          0 :         BUILD_BUG_ON(INTEL_FRONTBUFFER_BITS_PER_PIPE * I915_MAX_PIPES >
     302                 :            :                      BITS_PER_TYPE(atomic_t));
     303                 :            : 
     304         [ #  # ]:          0 :         if (old) {
     305         [ #  # ]:          0 :                 WARN_ON(!(atomic_read(&old->bits) & frontbuffer_bits));
     306                 :          0 :                 atomic_andnot(frontbuffer_bits, &old->bits);
     307                 :            :         }
     308                 :            : 
     309         [ #  # ]:          0 :         if (new) {
     310         [ #  # ]:          0 :                 WARN_ON(atomic_read(&new->bits) & frontbuffer_bits);
     311                 :          0 :                 atomic_or(frontbuffer_bits, &new->bits);
     312                 :            :         }
     313                 :          0 : }

Generated by: LCOV version 1.14