root/drivers/gpu/drm/msm/adreno/a5xx_gpu.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. spin_usecs
  2. a5xx_in_preempt

   1 /* SPDX-License-Identifier: GPL-2.0-only */
   2 /* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
   3  */
   4 #ifndef __A5XX_GPU_H__
   5 #define __A5XX_GPU_H__
   6 
   7 #include "adreno_gpu.h"
   8 
   9 /* Bringing over the hack from the previous targets */
  10 #undef ROP_COPY
  11 #undef ROP_XOR
  12 
  13 #include "a5xx.xml.h"
  14 
  15 struct a5xx_gpu {
  16         struct adreno_gpu base;
  17 
  18         struct drm_gem_object *pm4_bo;
  19         uint64_t pm4_iova;
  20 
  21         struct drm_gem_object *pfp_bo;
  22         uint64_t pfp_iova;
  23 
  24         struct drm_gem_object *gpmu_bo;
  25         uint64_t gpmu_iova;
  26         uint32_t gpmu_dwords;
  27 
  28         uint32_t lm_leakage;
  29 
  30         struct msm_ringbuffer *cur_ring;
  31         struct msm_ringbuffer *next_ring;
  32 
  33         struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS];
  34         struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS];
  35         uint64_t preempt_iova[MSM_GPU_MAX_RINGS];
  36 
  37         atomic_t preempt_state;
  38         struct timer_list preempt_timer;
  39 };
  40 
  41 #define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base)
  42 
  43 #ifdef CONFIG_DEBUG_FS
  44 int a5xx_debugfs_init(struct msm_gpu *gpu, struct drm_minor *minor);
  45 #endif
  46 
  47 /*
  48  * In order to do lockless preemption we use a simple state machine to progress
  49  * through the process.
  50  *
  51  * PREEMPT_NONE - no preemption in progress.  Next state START.
  52  * PREEMPT_START - The trigger is evaulating if preemption is possible. Next
  53  * states: TRIGGERED, NONE
  54  * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next
  55  * state: NONE.
  56  * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next
  57  * states: FAULTED, PENDING
  58  * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger
  59  * recovery.  Next state: N/A
  60  * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is
  61  * checking the success of the operation. Next state: FAULTED, NONE.
  62  */
  63 
  64 enum preempt_state {
  65         PREEMPT_NONE = 0,
  66         PREEMPT_START,
  67         PREEMPT_ABORT,
  68         PREEMPT_TRIGGERED,
  69         PREEMPT_FAULTED,
  70         PREEMPT_PENDING,
  71 };
  72 
  73 /*
  74  * struct a5xx_preempt_record is a shared buffer between the microcode and the
  75  * CPU to store the state for preemption. The record itself is much larger
  76  * (64k) but most of that is used by the CP for storage.
  77  *
  78  * There is a preemption record assigned per ringbuffer. When the CPU triggers a
  79  * preemption, it fills out the record with the useful information (wptr, ring
  80  * base, etc) and the microcode uses that information to set up the CP following
  81  * the preemption.  When a ring is switched out, the CP will save the ringbuffer
  82  * state back to the record. In this way, once the records are properly set up
  83  * the CPU can quickly switch back and forth between ringbuffers by only
  84  * updating a few registers (often only the wptr).
  85  *
  86  * These are the CPU aware registers in the record:
  87  * @magic: Must always be 0x27C4BAFC
  88  * @info: Type of the record - written 0 by the CPU, updated by the CP
  89  * @data: Data field from SET_RENDER_MODE or a checkpoint. Written and used by
  90  * the CP
  91  * @cntl: Value of RB_CNTL written by CPU, save/restored by CP
  92  * @rptr: Value of RB_RPTR written by CPU, save/restored by CP
  93  * @wptr: Value of RB_WPTR written by CPU, save/restored by CP
  94  * @rptr_addr: Value of RB_RPTR_ADDR written by CPU, save/restored by CP
  95  * @rbase: Value of RB_BASE written by CPU, save/restored by CP
  96  * @counter: GPU address of the storage area for the performance counters
  97  */
  98 struct a5xx_preempt_record {
  99         uint32_t magic;
 100         uint32_t info;
 101         uint32_t data;
 102         uint32_t cntl;
 103         uint32_t rptr;
 104         uint32_t wptr;
 105         uint64_t rptr_addr;
 106         uint64_t rbase;
 107         uint64_t counter;
 108 };
 109 
 110 /* Magic identifier for the preemption record */
 111 #define A5XX_PREEMPT_RECORD_MAGIC 0x27C4BAFCUL
 112 
 113 /*
 114  * Even though the structure above is only a few bytes, we need a full 64k to
 115  * store the entire preemption record from the CP
 116  */
 117 #define A5XX_PREEMPT_RECORD_SIZE (64 * 1024)
 118 
 119 /*
 120  * The preemption counter block is a storage area for the value of the
 121  * preemption counters that are saved immediately before context switch. We
 122  * append it on to the end of the allocation for the preemption record.
 123  */
 124 #define A5XX_PREEMPT_COUNTER_SIZE (16 * 4)
 125 
 126 
 127 int a5xx_power_init(struct msm_gpu *gpu);
 128 void a5xx_gpmu_ucode_init(struct msm_gpu *gpu);
 129 
 130 static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs,
 131                 uint32_t reg, uint32_t mask, uint32_t value)
 132 {
 133         while (usecs--) {
 134                 udelay(1);
 135                 if ((gpu_read(gpu, reg) & mask) == value)
 136                         return 0;
 137                 cpu_relax();
 138         }
 139 
 140         return -ETIMEDOUT;
 141 }
 142 
 143 bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
 144 void a5xx_set_hwcg(struct msm_gpu *gpu, bool state);
 145 
 146 void a5xx_preempt_init(struct msm_gpu *gpu);
 147 void a5xx_preempt_hw_init(struct msm_gpu *gpu);
 148 void a5xx_preempt_trigger(struct msm_gpu *gpu);
 149 void a5xx_preempt_irq(struct msm_gpu *gpu);
 150 void a5xx_preempt_fini(struct msm_gpu *gpu);
 151 
 152 /* Return true if we are in a preempt state */
 153 static inline bool a5xx_in_preempt(struct a5xx_gpu *a5xx_gpu)
 154 {
 155         int preempt_state = atomic_read(&a5xx_gpu->preempt_state);
 156 
 157         return !(preempt_state == PREEMPT_NONE ||
 158                         preempt_state == PREEMPT_ABORT);
 159 }
 160 
 161 #endif /* __A5XX_GPU_H__ */

/* [<][>][^][v][top][bottom][index][help] */