Merge tag 'drm-msm-fixes-2023-01-16' into msm-fixes
authorRob Clark <robdclark@chromium.org>
Wed, 22 Feb 2023 19:20:41 +0000 (11:20 -0800)
committerRob Clark <robdclark@chromium.org>
Wed, 22 Feb 2023 19:20:41 +0000 (11:20 -0800)
Back-merge of previous cycles msm-fixes for kexec fix (to avoid merge
conflict)

Signed-off-by: Rob Clark <robdclark@chromium.org>
1  2 
drivers/gpu/drm/msm/adreno/adreno_gpu.c
drivers/gpu/drm/msm/msm_gpu.c
drivers/gpu/drm/msm/msm_gpu.h

index 3bc02dbed9a73c2caec215e7ca79c910bf5b9286,3605f095b2de24bf20640a5b5efecba65b196b14..817599766329934142ba5072d97033bd664153ce
@@@ -352,6 -352,8 +352,8 @@@ int adreno_set_param(struct msm_gpu *gp
                /* Ensure string is null terminated: */
                str[len] = '\0';
  
+               mutex_lock(&gpu->lock);
                if (param == MSM_PARAM_COMM) {
                        paramp = &ctx->comm;
                } else {
                kfree(*paramp);
                *paramp = str;
  
+               mutex_unlock(&gpu->lock);
                return 0;
        }
        case MSM_PARAM_SYSPROF:
@@@ -1079,13 -1083,13 +1083,13 @@@ int adreno_gpu_init(struct drm_device *
  void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu)
  {
        struct msm_gpu *gpu = &adreno_gpu->base;
 -      struct msm_drm_private *priv = gpu->dev->dev_private;
 +      struct msm_drm_private *priv = gpu->dev ? gpu->dev->dev_private : NULL;
        unsigned int i;
  
        for (i = 0; i < ARRAY_SIZE(adreno_gpu->info->fw); i++)
                release_firmware(adreno_gpu->fw[i]);
  
 -      if (pm_runtime_enabled(&priv->gpu_pdev->dev))
 +      if (priv && pm_runtime_enabled(&priv->gpu_pdev->dev))
                pm_runtime_disable(&priv->gpu_pdev->dev);
  
        msm_gpu_cleanup(&adreno_gpu->base);
index 30ed45af76ade1de740a1f3bfcc7f00bd09b619e,4f495eecc34badc004a238fcb7ad6b3defd5fe00..3802495003258a1258650a2c73c1a0572283dfc6
@@@ -335,6 -335,8 +335,8 @@@ static void get_comm_cmdline(struct msm
        struct msm_file_private *ctx = submit->queue->ctx;
        struct task_struct *task;
  
+       WARN_ON(!mutex_is_locked(&submit->gpu->lock));
        /* Note that kstrdup will return NULL if argument is NULL: */
        *comm = kstrdup(ctx->comm, GFP_KERNEL);
        *cmd  = kstrdup(ctx->cmdline, GFP_KERNEL);
@@@ -492,21 -494,6 +494,21 @@@ static void hangcheck_timer_reset(struc
                        round_jiffies_up(jiffies + msecs_to_jiffies(priv->hangcheck_period)));
  }
  
 +static bool made_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
 +{
 +      if (ring->hangcheck_progress_retries >= DRM_MSM_HANGCHECK_PROGRESS_RETRIES)
 +              return false;
 +
 +      if (!gpu->funcs->progress)
 +              return false;
 +
 +      if (!gpu->funcs->progress(gpu, ring))
 +              return false;
 +
 +      ring->hangcheck_progress_retries++;
 +      return true;
 +}
 +
  static void hangcheck_handler(struct timer_list *t)
  {
        struct msm_gpu *gpu = from_timer(gpu, t, hangcheck_timer);
        if (fence != ring->hangcheck_fence) {
                /* some progress has been made.. ya! */
                ring->hangcheck_fence = fence;
 -      } else if (fence_before(fence, ring->fctx->last_fence)) {
 +              ring->hangcheck_progress_retries = 0;
 +      } else if (fence_before(fence, ring->fctx->last_fence) &&
 +                      !made_progress(gpu, ring)) {
                /* no progress and not done.. hung! */
                ring->hangcheck_fence = fence;
 +              ring->hangcheck_progress_retries = 0;
                DRM_DEV_ERROR(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n",
                                gpu->name, ring->id);
                DRM_DEV_ERROR(dev->dev, "%s:     completed fence: %u\n",
@@@ -848,7 -832,6 +850,7 @@@ int msm_gpu_init(struct drm_device *drm
                struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
                const char *name, struct msm_gpu_config *config)
  {
 +      struct msm_drm_private *priv = drm->dev_private;
        int i, ret, nr_rings = config->nr_rings;
        void *memptrs;
        uint64_t memptrs_iova;
        kthread_init_work(&gpu->recover_work, recover_worker);
        kthread_init_work(&gpu->fault_work, fault_worker);
  
 +      priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
 +
 +      /*
 +       * If progress detection is supported, halve the hangcheck timer
 +       * duration, as it takes two iterations of the hangcheck handler
 +       * to detect a hang.
 +       */
 +      if (funcs->progress)
 +              priv->hangcheck_period /= 2;
 +
        timer_setup(&gpu->hangcheck_timer, hangcheck_handler, 0);
  
        spin_lock_init(&gpu->perf_lock);
index a771f56ed70fd29cf431ffcaa806e10ccc2ca682,a89bfdc3d7f90f5db182c60aa91cdf28345baa01..fc1c0d8611a82b300b48819bdebd494c3ab5c19a
@@@ -78,15 -78,6 +78,15 @@@ struct msm_gpu_funcs 
        struct msm_gem_address_space *(*create_private_address_space)
                (struct msm_gpu *gpu);
        uint32_t (*get_rptr)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
 +
 +      /**
 +       * progress: Has the GPU made progress?
 +       *
 +       * Return true if GPU position in cmdstream has advanced (or changed)
 +       * since the last call.  To avoid false negatives, this should account
 +       * for cmdstream that is buffered in this FIFO upstream of the CP fw.
 +       */
 +      bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
  };
  
  /* Additional state for iommu faults: */
@@@ -109,15 -100,11 +109,15 @@@ struct msm_gpu_devfreq 
        struct mutex lock;
  
        /**
 -       * idle_constraint:
 +       * idle_freq:
         *
 -       * A PM QoS constraint to limit max freq while the GPU is idle.
 +       * Shadow frequency used while the GPU is idle.  From the PoV of
 +       * the devfreq governor, we are continuing to sample busyness and
 +       * adjust frequency while the GPU is idle, but we use this shadow
 +       * value as the GPU is actually clamped to minimum frequency while
 +       * it is inactive.
         */
 -      struct dev_pm_qos_request idle_freq;
 +      unsigned long idle_freq;
  
        /**
         * boost_constraint:
        /** idle_time: Time of last transition to idle: */
        ktime_t idle_time;
  
 -      struct devfreq_dev_status average_status;
 -
        /**
         * idle_work:
         *
@@@ -248,7 -237,6 +248,7 @@@ struct msm_gpu 
  #define DRM_MSM_INACTIVE_PERIOD   66 /* in ms (roughly four frames) */
  
  #define DRM_MSM_HANGCHECK_DEFAULT_PERIOD 500 /* in ms */
 +#define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3
        struct timer_list hangcheck_timer;
  
        /* Fault info for most recent iova fault: */
  
        struct msm_gpu_state *crashstate;
  
 -      /* Enable clamping to idle freq when inactive: */
 -      bool clamp_to_idle;
 -
        /* True if the hardware supports expanded apriv (a650 and newer) */
        bool hw_apriv;
  
@@@ -375,10 -366,18 +375,18 @@@ struct msm_file_private 
         */
        int sysprof;
  
-       /** comm: Overridden task comm, see MSM_PARAM_COMM */
+       /**
+        * comm: Overridden task comm, see MSM_PARAM_COMM
+        *
+        * Accessed under msm_gpu::lock
+        */
        char *comm;
  
-       /** cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE */
+       /**
+        * cmdline: Overridden task cmdline, see MSM_PARAM_CMDLINE
+        *
+        * Accessed under msm_gpu::lock
+        */
        char *cmdline;
  
        /**
@@@ -549,7 -548,7 +557,7 @@@ static inline void gpu_rmw(struct msm_g
        msm_rmw(gpu->mmio + (reg << 2), mask, or);
  }
  
 -static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
 +static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
  {
        u64 val;
  
         * when the lo is read, so make sure to read the lo first to trigger
         * that
         */
 -      val = (u64) msm_readl(gpu->mmio + (lo << 2));
 -      val |= ((u64) msm_readl(gpu->mmio + (hi << 2)) << 32);
 +      val = (u64) msm_readl(gpu->mmio + (reg << 2));
 +      val |= ((u64) msm_readl(gpu->mmio + ((reg + 1) << 2)) << 32);
  
        return val;
  }
  
 -static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
 +static inline void gpu_write64(struct msm_gpu *gpu, u32 reg, u64 val)
  {
        /* Why not a writeq here? Read the screed above */
 -      msm_writel(lower_32_bits(val), gpu->mmio + (lo << 2));
 -      msm_writel(upper_32_bits(val), gpu->mmio + (hi << 2));
 +      msm_writel(lower_32_bits(val), gpu->mmio + (reg << 2));
 +      msm_writel(upper_32_bits(val), gpu->mmio + ((reg + 1) << 2));
  }
  
  int msm_gpu_pm_suspend(struct msm_gpu *gpu);