LCOV - code coverage report
Current view: top level - drivers/gpu/drm/i915 - i915_pmu.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 550 0.0 %
Date: 2022-03-28 15:32:58 Functions: 0 34 0.0 %
Branches: 0 287 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * SPDX-License-Identifier: MIT
       3                 :            :  *
       4                 :            :  * Copyright © 2017-2018 Intel Corporation
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <linux/irq.h>
       8                 :            : #include <linux/pm_runtime.h>
       9                 :            : 
      10                 :            : #include "gt/intel_engine.h"
      11                 :            : #include "gt/intel_engine_pm.h"
      12                 :            : #include "gt/intel_engine_user.h"
      13                 :            : #include "gt/intel_gt_pm.h"
      14                 :            : #include "gt/intel_rc6.h"
      15                 :            : #include "gt/intel_rps.h"
      16                 :            : 
      17                 :            : #include "i915_drv.h"
      18                 :            : #include "i915_pmu.h"
      19                 :            : #include "intel_pm.h"
      20                 :            : 
      21                 :            : /* Frequency for the sampling timer for events which need it. */
      22                 :            : #define FREQUENCY 200
      23                 :            : #define PERIOD max_t(u64, 10000, NSEC_PER_SEC / FREQUENCY)
      24                 :            : 
      25                 :            : #define ENGINE_SAMPLE_MASK \
      26                 :            :         (BIT(I915_SAMPLE_BUSY) | \
      27                 :            :          BIT(I915_SAMPLE_WAIT) | \
      28                 :            :          BIT(I915_SAMPLE_SEMA))
      29                 :            : 
      30                 :            : #define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
      31                 :            : 
      32                 :            : static cpumask_t i915_pmu_cpumask;
      33                 :            : 
      34                 :          0 : static u8 engine_config_sample(u64 config)
      35                 :            : {
      36                 :          0 :         return config & I915_PMU_SAMPLE_MASK;
      37                 :            : }
      38                 :            : 
      39                 :          0 : static u8 engine_event_sample(struct perf_event *event)
      40                 :            : {
      41                 :          0 :         return engine_config_sample(event->attr.config);
      42                 :            : }
      43                 :            : 
      44                 :          0 : static u8 engine_event_class(struct perf_event *event)
      45                 :            : {
      46                 :          0 :         return (event->attr.config >> I915_PMU_CLASS_SHIFT) & 0xff;
      47                 :            : }
      48                 :            : 
      49                 :          0 : static u8 engine_event_instance(struct perf_event *event)
      50                 :            : {
      51                 :          0 :         return (event->attr.config >> I915_PMU_SAMPLE_BITS) & 0xff;
      52                 :            : }
      53                 :            : 
      54                 :          0 : static bool is_engine_config(u64 config)
      55                 :            : {
      56                 :          0 :         return config < __I915_PMU_OTHER(0);
      57                 :            : }
      58                 :            : 
      59                 :          0 : static unsigned int config_enabled_bit(u64 config)
      60                 :            : {
      61                 :          0 :         if (is_engine_config(config))
      62                 :          0 :                 return engine_config_sample(config);
      63                 :            :         else
      64                 :          0 :                 return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0));
      65                 :            : }
      66                 :            : 
      67                 :          0 : static u64 config_enabled_mask(u64 config)
      68                 :            : {
      69                 :          0 :         return BIT_ULL(config_enabled_bit(config));
      70                 :            : }
      71                 :            : 
      72                 :          0 : static bool is_engine_event(struct perf_event *event)
      73                 :            : {
      74                 :          0 :         return is_engine_config(event->attr.config);
      75                 :            : }
      76                 :            : 
      77                 :          0 : static unsigned int event_enabled_bit(struct perf_event *event)
      78                 :            : {
      79                 :          0 :         return config_enabled_bit(event->attr.config);
      80                 :            : }
      81                 :            : 
      82                 :          0 : static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
      83                 :            : {
      84                 :          0 :         struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
      85                 :          0 :         u64 enable;
      86                 :            : 
      87                 :            :         /*
      88                 :            :          * Only some counters need the sampling timer.
      89                 :            :          *
      90                 :            :          * We start with a bitmask of all currently enabled events.
      91                 :            :          */
      92                 :          0 :         enable = pmu->enable;
      93                 :            : 
      94                 :            :         /*
      95                 :            :          * Mask out all the ones which do not need the timer, or in
      96                 :            :          * other words keep all the ones that could need the timer.
      97                 :            :          */
      98                 :          0 :         enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
      99                 :            :                   config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
     100                 :            :                   ENGINE_SAMPLE_MASK;
     101                 :            : 
     102                 :            :         /*
     103                 :            :          * When the GPU is idle per-engine counters do not need to be
     104                 :            :          * running so clear those bits out.
     105                 :            :          */
     106                 :          0 :         if (!gpu_active)
     107                 :          0 :                 enable &= ~ENGINE_SAMPLE_MASK;
     108                 :            :         /*
     109                 :            :          * Also there is software busyness tracking available we do not
     110                 :            :          * need the timer for I915_SAMPLE_BUSY counter.
     111                 :            :          */
     112         [ #  # ]:          0 :         else if (i915->caps.scheduler & I915_SCHEDULER_CAP_ENGINE_BUSY_STATS)
     113                 :          0 :                 enable &= ~BIT(I915_SAMPLE_BUSY);
     114                 :            : 
     115                 :            :         /*
     116                 :            :          * If some bits remain it means we need the sampling timer running.
     117                 :            :          */
     118                 :          0 :         return enable;
     119                 :            : }
     120                 :            : 
     121                 :          0 : static u64 __get_rc6(struct intel_gt *gt)
     122                 :            : {
     123                 :          0 :         struct drm_i915_private *i915 = gt->i915;
     124                 :          0 :         u64 val;
     125                 :            : 
     126         [ #  # ]:          0 :         val = intel_rc6_residency_ns(&gt->rc6,
     127                 :            :                                      IS_VALLEYVIEW(i915) ?
     128                 :            :                                      VLV_GT_RENDER_RC6 :
     129                 :            :                                      GEN6_GT_GFX_RC6);
     130                 :            : 
     131         [ #  # ]:          0 :         if (HAS_RC6p(i915))
     132                 :          0 :                 val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6p);
     133                 :            : 
     134                 :          0 :         if (HAS_RC6pp(i915))
     135                 :            :                 val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6pp);
     136                 :            : 
     137                 :          0 :         return val;
     138                 :            : }
     139                 :            : 
     140                 :            : #if IS_ENABLED(CONFIG_PM)
     141                 :            : 
     142                 :          0 : static inline s64 ktime_since(const ktime_t kt)
     143                 :            : {
     144                 :          0 :         return ktime_to_ns(ktime_sub(ktime_get(), kt));
     145                 :            : }
     146                 :            : 
     147                 :          0 : static u64 get_rc6(struct intel_gt *gt)
     148                 :            : {
     149                 :          0 :         struct drm_i915_private *i915 = gt->i915;
     150                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     151                 :          0 :         unsigned long flags;
     152                 :          0 :         bool awake = false;
     153                 :          0 :         u64 val;
     154                 :            : 
     155         [ #  # ]:          0 :         if (intel_gt_pm_get_if_awake(gt)) {
     156                 :          0 :                 val = __get_rc6(gt);
     157                 :          0 :                 intel_gt_pm_put_async(gt);
     158                 :          0 :                 awake = true;
     159                 :            :         }
     160                 :            : 
     161                 :          0 :         spin_lock_irqsave(&pmu->lock, flags);
     162                 :            : 
     163         [ #  # ]:          0 :         if (awake) {
     164                 :          0 :                 pmu->sample[__I915_SAMPLE_RC6].cur = val;
     165                 :            :         } else {
     166                 :            :                 /*
     167                 :            :                  * We think we are runtime suspended.
     168                 :            :                  *
     169                 :            :                  * Report the delta from when the device was suspended to now,
     170                 :            :                  * on top of the last known real value, as the approximated RC6
     171                 :            :                  * counter value.
     172                 :            :                  */
     173                 :          0 :                 val = ktime_since(pmu->sleep_last);
     174                 :          0 :                 val += pmu->sample[__I915_SAMPLE_RC6].cur;
     175                 :            :         }
     176                 :            : 
     177         [ #  # ]:          0 :         if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur)
     178                 :            :                 val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur;
     179                 :            :         else
     180                 :          0 :                 pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val;
     181                 :            : 
     182                 :          0 :         spin_unlock_irqrestore(&pmu->lock, flags);
     183                 :            : 
     184                 :          0 :         return val;
     185                 :            : }
     186                 :            : 
     187                 :          0 : static void park_rc6(struct drm_i915_private *i915)
     188                 :            : {
     189                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     190                 :            : 
     191         [ #  # ]:          0 :         if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
     192                 :          0 :                 pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
     193                 :            : 
     194                 :          0 :         pmu->sleep_last = ktime_get();
     195                 :          0 : }
     196                 :            : 
     197                 :            : #else
     198                 :            : 
     199                 :            : static u64 get_rc6(struct intel_gt *gt)
     200                 :            : {
     201                 :            :         return __get_rc6(gt);
     202                 :            : }
     203                 :            : 
     204                 :            : static void park_rc6(struct drm_i915_private *i915) {}
     205                 :            : 
     206                 :            : #endif
     207                 :            : 
     208                 :          0 : static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
     209                 :            : {
     210   [ #  #  #  # ]:          0 :         if (!pmu->timer_enabled && pmu_needs_timer(pmu, true)) {
     211                 :          0 :                 pmu->timer_enabled = true;
     212                 :          0 :                 pmu->timer_last = ktime_get();
     213                 :          0 :                 hrtimer_start_range_ns(&pmu->timer,
     214                 :            :                                        ns_to_ktime(PERIOD), 0,
     215                 :            :                                        HRTIMER_MODE_REL_PINNED);
     216                 :            :         }
     217                 :          0 : }
     218                 :            : 
     219                 :          0 : void i915_pmu_gt_parked(struct drm_i915_private *i915)
     220                 :            : {
     221                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     222                 :            : 
     223         [ #  # ]:          0 :         if (!pmu->base.event_init)
     224                 :            :                 return;
     225                 :            : 
     226                 :          0 :         spin_lock_irq(&pmu->lock);
     227                 :            : 
     228                 :          0 :         park_rc6(i915);
     229                 :            : 
     230                 :            :         /*
     231                 :            :          * Signal sampling timer to stop if only engine events are enabled and
     232                 :            :          * GPU went idle.
     233                 :            :          */
     234                 :          0 :         pmu->timer_enabled = pmu_needs_timer(pmu, false);
     235                 :            : 
     236                 :          0 :         spin_unlock_irq(&pmu->lock);
     237                 :            : }
     238                 :            : 
     239                 :          0 : void i915_pmu_gt_unparked(struct drm_i915_private *i915)
     240                 :            : {
     241                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     242                 :            : 
     243         [ #  # ]:          0 :         if (!pmu->base.event_init)
     244                 :            :                 return;
     245                 :            : 
     246                 :          0 :         spin_lock_irq(&pmu->lock);
     247                 :            : 
     248                 :            :         /*
     249                 :            :          * Re-enable sampling timer when GPU goes active.
     250                 :            :          */
     251                 :          0 :         __i915_pmu_maybe_start_timer(pmu);
     252                 :            : 
     253                 :          0 :         spin_unlock_irq(&pmu->lock);
     254                 :            : }
     255                 :            : 
     256                 :            : static void
     257                 :          0 : add_sample(struct i915_pmu_sample *sample, u32 val)
     258                 :            : {
     259                 :          0 :         sample->cur += val;
     260                 :          0 : }
     261                 :            : 
     262                 :          0 : static bool exclusive_mmio_access(const struct drm_i915_private *i915)
     263                 :            : {
     264                 :            :         /*
     265                 :            :          * We have to avoid concurrent mmio cache line access on gen7 or
     266                 :            :          * risk a machine hang. For a fun history lesson dig out the old
     267                 :            :          * userspace intel_gpu_top and run it on Ivybridge or Haswell!
     268                 :            :          */
     269                 :          0 :         return IS_GEN(i915, 7);
     270                 :            : }
     271                 :            : 
     272                 :            : static void
     273                 :          0 : engines_sample(struct intel_gt *gt, unsigned int period_ns)
     274                 :            : {
     275                 :          0 :         struct drm_i915_private *i915 = gt->i915;
     276                 :          0 :         struct intel_engine_cs *engine;
     277                 :          0 :         enum intel_engine_id id;
     278                 :            : 
     279         [ #  # ]:          0 :         if ((i915->pmu.enable & ENGINE_SAMPLE_MASK) == 0)
     280                 :            :                 return;
     281                 :            : 
     282         [ #  # ]:          0 :         if (!intel_gt_pm_is_awake(gt))
     283                 :            :                 return;
     284                 :            : 
     285   [ #  #  #  # ]:          0 :         for_each_engine(engine, gt, id) {
     286                 :          0 :                 struct intel_engine_pmu *pmu = &engine->pmu;
     287                 :          0 :                 spinlock_t *mmio_lock;
     288                 :          0 :                 unsigned long flags;
     289                 :          0 :                 bool busy;
     290                 :          0 :                 u32 val;
     291                 :            : 
     292         [ #  # ]:          0 :                 if (!intel_engine_pm_get_if_awake(engine))
     293                 :          0 :                         continue;
     294                 :            : 
     295                 :          0 :                 mmio_lock = NULL;
     296         [ #  # ]:          0 :                 if (exclusive_mmio_access(i915))
     297                 :          0 :                         mmio_lock = &engine->uncore->lock;
     298                 :            : 
     299         [ #  # ]:          0 :                 if (unlikely(mmio_lock))
     300                 :          0 :                         spin_lock_irqsave(mmio_lock, flags);
     301                 :            : 
     302                 :          0 :                 val = ENGINE_READ_FW(engine, RING_CTL);
     303         [ #  # ]:          0 :                 if (val == 0) /* powerwell off => engine idle */
     304                 :          0 :                         goto skip;
     305                 :            : 
     306         [ #  # ]:          0 :                 if (val & RING_WAIT)
     307                 :          0 :                         add_sample(&pmu->sample[I915_SAMPLE_WAIT], period_ns);
     308         [ #  # ]:          0 :                 if (val & RING_WAIT_SEMAPHORE)
     309                 :          0 :                         add_sample(&pmu->sample[I915_SAMPLE_SEMA], period_ns);
     310                 :            : 
     311                 :            :                 /* No need to sample when busy stats are supported. */
     312         [ #  # ]:          0 :                 if (intel_engine_supports_stats(engine))
     313                 :          0 :                         goto skip;
     314                 :            : 
     315                 :            :                 /*
     316                 :            :                  * While waiting on a semaphore or event, MI_MODE reports the
     317                 :            :                  * ring as idle. However, previously using the seqno, and with
     318                 :            :                  * execlists sampling, we account for the ring waiting as the
     319                 :            :                  * engine being busy. Therefore, we record the sample as being
     320                 :            :                  * busy if either waiting or !idle.
     321                 :            :                  */
     322                 :          0 :                 busy = val & (RING_WAIT_SEMAPHORE | RING_WAIT);
     323         [ #  # ]:          0 :                 if (!busy) {
     324                 :          0 :                         val = ENGINE_READ_FW(engine, RING_MI_MODE);
     325                 :          0 :                         busy = !(val & MODE_IDLE);
     326                 :            :                 }
     327         [ #  # ]:          0 :                 if (busy)
     328                 :          0 :                         add_sample(&pmu->sample[I915_SAMPLE_BUSY], period_ns);
     329                 :            : 
     330                 :          0 : skip:
     331         [ #  # ]:          0 :                 if (unlikely(mmio_lock))
     332                 :          0 :                         spin_unlock_irqrestore(mmio_lock, flags);
     333                 :          0 :                 intel_engine_pm_put_async(engine);
     334                 :            :         }
     335                 :            : }
     336                 :            : 
     337                 :            : static void
     338                 :          0 : add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)
     339                 :            : {
     340                 :          0 :         sample->cur += mul_u32_u32(val, mul);
     341                 :          0 : }
     342                 :            : 
     343                 :          0 : static bool frequency_sampling_enabled(struct i915_pmu *pmu)
     344                 :            : {
     345                 :          0 :         return pmu->enable &
     346                 :            :                (config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
     347                 :            :                 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY));
     348                 :            : }
     349                 :            : 
     350                 :            : static void
     351                 :          0 : frequency_sample(struct intel_gt *gt, unsigned int period_ns)
     352                 :            : {
     353                 :          0 :         struct drm_i915_private *i915 = gt->i915;
     354                 :          0 :         struct intel_uncore *uncore = gt->uncore;
     355                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     356                 :          0 :         struct intel_rps *rps = &gt->rps;
     357                 :            : 
     358         [ #  # ]:          0 :         if (!frequency_sampling_enabled(pmu))
     359                 :            :                 return;
     360                 :            : 
     361                 :            :         /* Report 0/0 (actual/requested) frequency while parked. */
     362         [ #  # ]:          0 :         if (!intel_gt_pm_get_if_awake(gt))
     363                 :            :                 return;
     364                 :            : 
     365         [ #  # ]:          0 :         if (pmu->enable & config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
     366                 :          0 :                 u32 val;
     367                 :            : 
     368                 :            :                 /*
     369                 :            :                  * We take a quick peek here without using forcewake
     370                 :            :                  * so that we don't perturb the system under observation
     371                 :            :                  * (forcewake => !rc6 => increased power use). We expect
     372                 :            :                  * that if the read fails because it is outside of the
     373                 :            :                  * mmio power well, then it will return 0 -- in which
     374                 :            :                  * case we assume the system is running at the intended
     375                 :            :                  * frequency. Fortunately, the read should rarely fail!
     376                 :            :                  */
     377                 :          0 :                 val = intel_uncore_read_fw(uncore, GEN6_RPSTAT1);
     378         [ #  # ]:          0 :                 if (val)
     379                 :          0 :                         val = intel_rps_get_cagf(rps, val);
     380                 :            :                 else
     381                 :          0 :                         val = rps->cur_freq;
     382                 :            : 
     383                 :          0 :                 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],
     384                 :          0 :                                 intel_gpu_freq(rps, val), period_ns / 1000);
     385                 :            :         }
     386                 :            : 
     387         [ #  # ]:          0 :         if (pmu->enable & config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
     388                 :          0 :                 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
     389                 :          0 :                                 intel_gpu_freq(rps, rps->cur_freq),
     390                 :            :                                 period_ns / 1000);
     391                 :            :         }
     392                 :            : 
     393                 :          0 :         intel_gt_pm_put_async(gt);
     394                 :            : }
     395                 :            : 
     396                 :          0 : static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
     397                 :            : {
     398                 :          0 :         struct drm_i915_private *i915 =
     399                 :          0 :                 container_of(hrtimer, struct drm_i915_private, pmu.timer);
     400                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     401                 :          0 :         struct intel_gt *gt = &i915->gt;
     402                 :          0 :         unsigned int period_ns;
     403                 :          0 :         ktime_t now;
     404                 :            : 
     405         [ #  # ]:          0 :         if (!READ_ONCE(pmu->timer_enabled))
     406                 :            :                 return HRTIMER_NORESTART;
     407                 :            : 
     408                 :          0 :         now = ktime_get();
     409                 :          0 :         period_ns = ktime_to_ns(ktime_sub(now, pmu->timer_last));
     410                 :          0 :         pmu->timer_last = now;
     411                 :            : 
     412                 :            :         /*
     413                 :            :          * Strictly speaking the passed in period may not be 100% accurate for
     414                 :            :          * all internal calculation, since some amount of time can be spent on
     415                 :            :          * grabbing the forcewake. However the potential error from timer call-
     416                 :            :          * back delay greatly dominates this so we keep it simple.
     417                 :            :          */
     418                 :          0 :         engines_sample(gt, period_ns);
     419                 :          0 :         frequency_sample(gt, period_ns);
     420                 :            : 
     421                 :          0 :         hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));
     422                 :            : 
     423                 :          0 :         return HRTIMER_RESTART;
     424                 :            : }
     425                 :            : 
     426                 :            : static u64 count_interrupts(struct drm_i915_private *i915)
     427                 :            : {
     428                 :            :         /* open-coded kstat_irqs() */
     429                 :            :         struct irq_desc *desc = irq_to_desc(i915->drm.pdev->irq);
     430                 :            :         u64 sum = 0;
     431                 :            :         int cpu;
     432                 :            : 
     433                 :            :         if (!desc || !desc->kstat_irqs)
     434                 :            :                 return 0;
     435                 :            : 
     436                 :            :         for_each_possible_cpu(cpu)
     437                 :            :                 sum += *per_cpu_ptr(desc->kstat_irqs, cpu);
     438                 :            : 
     439                 :            :         return sum;
     440                 :            : }
     441                 :            : 
     442                 :          0 : static void engine_event_destroy(struct perf_event *event)
     443                 :            : {
     444                 :          0 :         struct drm_i915_private *i915 =
     445                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     446                 :          0 :         struct intel_engine_cs *engine;
     447                 :            : 
     448                 :          0 :         engine = intel_engine_lookup_user(i915,
     449                 :            :                                           engine_event_class(event),
     450                 :          0 :                                           engine_event_instance(event));
     451   [ #  #  #  #  :          0 :         if (WARN_ON_ONCE(!engine))
                   #  # ]
     452                 :            :                 return;
     453                 :            : 
     454   [ #  #  #  # ]:          0 :         if (engine_event_sample(event) == I915_SAMPLE_BUSY &&
     455         [ #  # ]:          0 :             intel_engine_supports_stats(engine))
     456                 :          0 :                 intel_disable_engine_stats(engine);
     457                 :            : }
     458                 :            : 
     459                 :          0 : static void i915_pmu_event_destroy(struct perf_event *event)
     460                 :            : {
     461         [ #  # ]:          0 :         WARN_ON(event->parent);
     462                 :            : 
     463         [ #  # ]:          0 :         if (is_engine_event(event))
     464                 :          0 :                 engine_event_destroy(event);
     465                 :          0 : }
     466                 :            : 
     467                 :            : static int
     468                 :          0 : engine_event_status(struct intel_engine_cs *engine,
     469                 :            :                     enum drm_i915_pmu_engine_sample sample)
     470                 :            : {
     471                 :          0 :         switch (sample) {
     472                 :            :         case I915_SAMPLE_BUSY:
     473                 :            :         case I915_SAMPLE_WAIT:
     474                 :            :                 break;
     475                 :          0 :         case I915_SAMPLE_SEMA:
     476   [ #  #  #  #  :          0 :                 if (INTEL_GEN(engine->i915) < 6)
                   #  # ]
     477                 :            :                         return -ENODEV;
     478                 :            :                 break;
     479                 :            :         default:
     480                 :            :                 return -ENOENT;
     481                 :            :         }
     482                 :            : 
     483                 :          0 :         return 0;
     484                 :            : }
     485                 :            : 
     486                 :            : static int
     487                 :          0 : config_status(struct drm_i915_private *i915, u64 config)
     488                 :            : {
     489   [ #  #  #  #  :          0 :         switch (config) {
                      # ]
     490                 :            :         case I915_PMU_ACTUAL_FREQUENCY:
     491   [ #  #  #  # ]:          0 :                 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
     492                 :            :                         /* Requires a mutex for sampling! */
     493                 :          0 :                         return -ENODEV;
     494                 :            :                 /* Fall-through. */
     495                 :            :         case I915_PMU_REQUESTED_FREQUENCY:
     496         [ #  # ]:          0 :                 if (INTEL_GEN(i915) < 6)
     497                 :          0 :                         return -ENODEV;
     498                 :            :                 break;
     499                 :            :         case I915_PMU_INTERRUPTS:
     500                 :            :                 break;
     501                 :          0 :         case I915_PMU_RC6_RESIDENCY:
     502         [ #  # ]:          0 :                 if (!HAS_RC6(i915))
     503                 :          0 :                         return -ENODEV;
     504                 :            :                 break;
     505                 :            :         default:
     506                 :            :                 return -ENOENT;
     507                 :            :         }
     508                 :            : 
     509                 :            :         return 0;
     510                 :            : }
     511                 :            : 
     512                 :          0 : static int engine_event_init(struct perf_event *event)
     513                 :            : {
     514                 :          0 :         struct drm_i915_private *i915 =
     515                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     516                 :          0 :         struct intel_engine_cs *engine;
     517                 :          0 :         u8 sample;
     518                 :          0 :         int ret;
     519                 :            : 
     520                 :          0 :         engine = intel_engine_lookup_user(i915, engine_event_class(event),
     521                 :          0 :                                           engine_event_instance(event));
     522         [ #  # ]:          0 :         if (!engine)
     523                 :            :                 return -ENODEV;
     524                 :            : 
     525                 :          0 :         sample = engine_event_sample(event);
     526      [ #  #  # ]:          0 :         ret = engine_event_status(engine, sample);
     527                 :          0 :         if (ret)
     528                 :          0 :                 return ret;
     529                 :            : 
     530   [ #  #  #  # ]:          0 :         if (sample == I915_SAMPLE_BUSY && intel_engine_supports_stats(engine))
     531                 :          0 :                 ret = intel_enable_engine_stats(engine);
     532                 :            : 
     533                 :            :         return ret;
     534                 :            : }
     535                 :            : 
     536                 :          0 : static int i915_pmu_event_init(struct perf_event *event)
     537                 :            : {
     538                 :          0 :         struct drm_i915_private *i915 =
     539                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     540                 :          0 :         int ret;
     541                 :            : 
     542         [ #  # ]:          0 :         if (event->attr.type != event->pmu->type)
     543                 :            :                 return -ENOENT;
     544                 :            : 
     545                 :            :         /* unsupported modes and filters */
     546         [ #  # ]:          0 :         if (event->attr.sample_period) /* no sampling */
     547                 :            :                 return -EINVAL;
     548                 :            : 
     549         [ #  # ]:          0 :         if (has_branch_stack(event))
     550                 :            :                 return -EOPNOTSUPP;
     551                 :            : 
     552         [ #  # ]:          0 :         if (event->cpu < 0)
     553                 :            :                 return -EINVAL;
     554                 :            : 
     555                 :            :         /* only allow running on one cpu at a time */
     556         [ #  # ]:          0 :         if (!cpumask_test_cpu(event->cpu, &i915_pmu_cpumask))
     557                 :            :                 return -EINVAL;
     558                 :            : 
     559         [ #  # ]:          0 :         if (is_engine_event(event))
     560                 :          0 :                 ret = engine_event_init(event);
     561                 :            :         else
     562                 :          0 :                 ret = config_status(i915, event->attr.config);
     563         [ #  # ]:          0 :         if (ret)
     564                 :            :                 return ret;
     565                 :            : 
     566         [ #  # ]:          0 :         if (!event->parent)
     567                 :          0 :                 event->destroy = i915_pmu_event_destroy;
     568                 :            : 
     569                 :            :         return 0;
     570                 :            : }
     571                 :            : 
     572                 :          0 : static u64 __i915_pmu_event_read(struct perf_event *event)
     573                 :            : {
     574                 :          0 :         struct drm_i915_private *i915 =
     575                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     576                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     577                 :          0 :         u64 val = 0;
     578                 :            : 
     579         [ #  # ]:          0 :         if (is_engine_event(event)) {
     580                 :          0 :                 u8 sample = engine_event_sample(event);
     581                 :          0 :                 struct intel_engine_cs *engine;
     582                 :            : 
     583                 :          0 :                 engine = intel_engine_lookup_user(i915,
     584                 :            :                                                   engine_event_class(event),
     585                 :            :                                                   engine_event_instance(event));
     586                 :            : 
     587   [ #  #  #  #  :          0 :                 if (WARN_ON_ONCE(!engine)) {
                   #  # ]
     588                 :            :                         /* Do nothing */
     589   [ #  #  #  # ]:          0 :                 } else if (sample == I915_SAMPLE_BUSY &&
     590         [ #  # ]:          0 :                            intel_engine_supports_stats(engine)) {
     591                 :          0 :                         val = ktime_to_ns(intel_engine_get_busy_time(engine));
     592                 :            :                 } else {
     593                 :          0 :                         val = engine->pmu.sample[sample].cur;
     594                 :            :                 }
     595                 :            :         } else {
     596   [ #  #  #  #  :          0 :                 switch (event->attr.config) {
                      # ]
     597                 :          0 :                 case I915_PMU_ACTUAL_FREQUENCY:
     598                 :          0 :                         val =
     599                 :          0 :                            div_u64(pmu->sample[__I915_SAMPLE_FREQ_ACT].cur,
     600                 :            :                                    USEC_PER_SEC /* to MHz */);
     601                 :          0 :                         break;
     602                 :          0 :                 case I915_PMU_REQUESTED_FREQUENCY:
     603                 :          0 :                         val =
     604                 :          0 :                            div_u64(pmu->sample[__I915_SAMPLE_FREQ_REQ].cur,
     605                 :            :                                    USEC_PER_SEC /* to MHz */);
     606                 :          0 :                         break;
     607                 :          0 :                 case I915_PMU_INTERRUPTS:
     608                 :          0 :                         val = count_interrupts(i915);
     609                 :          0 :                         break;
     610                 :          0 :                 case I915_PMU_RC6_RESIDENCY:
     611                 :          0 :                         val = get_rc6(&i915->gt);
     612                 :          0 :                         break;
     613                 :            :                 }
     614                 :          0 :         }
     615                 :            : 
     616                 :          0 :         return val;
     617                 :            : }
     618                 :            : 
     619                 :          0 : static void i915_pmu_event_read(struct perf_event *event)
     620                 :            : {
     621                 :          0 :         struct hw_perf_event *hwc = &event->hw;
     622                 :          0 :         u64 prev, new;
     623                 :            : 
     624                 :          0 : again:
     625                 :          0 :         prev = local64_read(&hwc->prev_count);
     626                 :          0 :         new = __i915_pmu_event_read(event);
     627                 :            : 
     628         [ #  # ]:          0 :         if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev)
     629                 :          0 :                 goto again;
     630                 :            : 
     631                 :          0 :         local64_add(new - prev, &event->count);
     632                 :          0 : }
     633                 :            : 
     634                 :          0 : static void i915_pmu_enable(struct perf_event *event)
     635                 :            : {
     636                 :          0 :         struct drm_i915_private *i915 =
     637                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     638         [ #  # ]:          0 :         unsigned int bit = event_enabled_bit(event);
     639                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     640                 :          0 :         intel_wakeref_t wakeref;
     641                 :          0 :         unsigned long flags;
     642                 :            : 
     643                 :          0 :         wakeref = intel_runtime_pm_get(&i915->runtime_pm);
     644                 :          0 :         spin_lock_irqsave(&pmu->lock, flags);
     645                 :            : 
     646                 :            :         /*
     647                 :            :          * Update the bitmask of enabled events and increment
     648                 :            :          * the event reference counter.
     649                 :            :          */
     650                 :          0 :         BUILD_BUG_ON(ARRAY_SIZE(pmu->enable_count) != I915_PMU_MASK_BITS);
     651                 :          0 :         GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
     652                 :          0 :         GEM_BUG_ON(pmu->enable_count[bit] == ~0);
     653                 :            : 
     654   [ #  #  #  # ]:          0 :         if (pmu->enable_count[bit] == 0 &&
     655                 :            :             config_enabled_mask(I915_PMU_RC6_RESIDENCY) & BIT_ULL(bit)) {
     656                 :          0 :                 pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = 0;
     657                 :          0 :                 pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
     658                 :          0 :                 pmu->sleep_last = ktime_get();
     659                 :            :         }
     660                 :            : 
     661                 :          0 :         pmu->enable |= BIT_ULL(bit);
     662                 :          0 :         pmu->enable_count[bit]++;
     663                 :            : 
     664                 :            :         /*
     665                 :            :          * Start the sampling timer if needed and not already enabled.
     666                 :            :          */
     667                 :          0 :         __i915_pmu_maybe_start_timer(pmu);
     668                 :            : 
     669                 :            :         /*
     670                 :            :          * For per-engine events the bitmask and reference counting
     671                 :            :          * is stored per engine.
     672                 :            :          */
     673         [ #  # ]:          0 :         if (is_engine_event(event)) {
     674                 :          0 :                 u8 sample = engine_event_sample(event);
     675                 :          0 :                 struct intel_engine_cs *engine;
     676                 :            : 
     677                 :          0 :                 engine = intel_engine_lookup_user(i915,
     678                 :            :                                                   engine_event_class(event),
     679                 :            :                                                   engine_event_instance(event));
     680                 :            : 
     681                 :          0 :                 BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
     682                 :            :                              I915_ENGINE_SAMPLE_COUNT);
     683                 :          0 :                 BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
     684                 :            :                              I915_ENGINE_SAMPLE_COUNT);
     685                 :          0 :                 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
     686                 :          0 :                 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
     687                 :          0 :                 GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
     688                 :            : 
     689                 :          0 :                 engine->pmu.enable |= BIT(sample);
     690                 :          0 :                 engine->pmu.enable_count[sample]++;
     691                 :            :         }
     692                 :            : 
     693                 :          0 :         spin_unlock_irqrestore(&pmu->lock, flags);
     694                 :            : 
     695                 :            :         /*
     696                 :            :          * Store the current counter value so we can report the correct delta
     697                 :            :          * for all listeners. Even when the event was already enabled and has
     698                 :            :          * an existing non-zero value.
     699                 :            :          */
     700                 :          0 :         local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
     701                 :            : 
     702                 :          0 :         intel_runtime_pm_put(&i915->runtime_pm, wakeref);
     703                 :          0 : }
     704                 :            : 
     705                 :          0 : static void i915_pmu_disable(struct perf_event *event)
     706                 :            : {
     707                 :          0 :         struct drm_i915_private *i915 =
     708                 :          0 :                 container_of(event->pmu, typeof(*i915), pmu.base);
     709         [ #  # ]:          0 :         unsigned int bit = event_enabled_bit(event);
     710                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
     711                 :          0 :         unsigned long flags;
     712                 :            : 
     713                 :          0 :         spin_lock_irqsave(&pmu->lock, flags);
     714                 :            : 
     715         [ #  # ]:          0 :         if (is_engine_event(event)) {
     716                 :          0 :                 u8 sample = engine_event_sample(event);
     717                 :          0 :                 struct intel_engine_cs *engine;
     718                 :            : 
     719                 :          0 :                 engine = intel_engine_lookup_user(i915,
     720                 :            :                                                   engine_event_class(event),
     721                 :            :                                                   engine_event_instance(event));
     722                 :            : 
     723                 :          0 :                 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
     724                 :          0 :                 GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
     725                 :          0 :                 GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
     726                 :            : 
     727                 :            :                 /*
     728                 :            :                  * Decrement the reference count and clear the enabled
     729                 :            :                  * bitmask when the last listener on an event goes away.
     730                 :            :                  */
     731         [ #  # ]:          0 :                 if (--engine->pmu.enable_count[sample] == 0)
     732                 :          0 :                         engine->pmu.enable &= ~BIT(sample);
     733                 :            :         }
     734                 :            : 
     735                 :          0 :         GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
     736                 :          0 :         GEM_BUG_ON(pmu->enable_count[bit] == 0);
     737                 :            :         /*
     738                 :            :          * Decrement the reference count and clear the enabled
     739                 :            :          * bitmask when the last listener on an event goes away.
     740                 :            :          */
     741         [ #  # ]:          0 :         if (--pmu->enable_count[bit] == 0) {
     742                 :          0 :                 pmu->enable &= ~BIT_ULL(bit);
     743         [ #  # ]:          0 :                 pmu->timer_enabled &= pmu_needs_timer(pmu, true);
     744                 :            :         }
     745                 :            : 
     746                 :          0 :         spin_unlock_irqrestore(&pmu->lock, flags);
     747                 :          0 : }
     748                 :            : 
     749                 :          0 : static void i915_pmu_event_start(struct perf_event *event, int flags)
     750                 :            : {
     751                 :          0 :         i915_pmu_enable(event);
     752                 :          0 :         event->hw.state = 0;
     753                 :          0 : }
     754                 :            : 
     755                 :          0 : static void i915_pmu_event_stop(struct perf_event *event, int flags)
     756                 :            : {
     757         [ #  # ]:          0 :         if (flags & PERF_EF_UPDATE)
     758                 :          0 :                 i915_pmu_event_read(event);
     759                 :          0 :         i915_pmu_disable(event);
     760                 :          0 :         event->hw.state = PERF_HES_STOPPED;
     761                 :          0 : }
     762                 :            : 
     763                 :          0 : static int i915_pmu_event_add(struct perf_event *event, int flags)
     764                 :            : {
     765         [ #  # ]:          0 :         if (flags & PERF_EF_START)
     766                 :          0 :                 i915_pmu_event_start(event, flags);
     767                 :            : 
     768                 :          0 :         return 0;
     769                 :            : }
     770                 :            : 
     771                 :          0 : static void i915_pmu_event_del(struct perf_event *event, int flags)
     772                 :            : {
     773                 :          0 :         i915_pmu_event_stop(event, PERF_EF_UPDATE);
     774                 :          0 : }
     775                 :            : 
     776                 :          0 : static int i915_pmu_event_event_idx(struct perf_event *event)
     777                 :            : {
     778                 :          0 :         return 0;
     779                 :            : }
     780                 :            : 
     781                 :            : struct i915_str_attribute {
     782                 :            :         struct device_attribute attr;
     783                 :            :         const char *str;
     784                 :            : };
     785                 :            : 
     786                 :          0 : static ssize_t i915_pmu_format_show(struct device *dev,
     787                 :            :                                     struct device_attribute *attr, char *buf)
     788                 :            : {
     789                 :          0 :         struct i915_str_attribute *eattr;
     790                 :            : 
     791                 :          0 :         eattr = container_of(attr, struct i915_str_attribute, attr);
     792                 :          0 :         return sprintf(buf, "%s\n", eattr->str);
     793                 :            : }
     794                 :            : 
     795                 :            : #define I915_PMU_FORMAT_ATTR(_name, _config) \
     796                 :            :         (&((struct i915_str_attribute[]) { \
     797                 :            :                 { .attr = __ATTR(_name, 0444, i915_pmu_format_show, NULL), \
     798                 :            :                   .str = _config, } \
     799                 :            :         })[0].attr.attr)
     800                 :            : 
     801                 :            : static struct attribute *i915_pmu_format_attrs[] = {
     802                 :            :         I915_PMU_FORMAT_ATTR(i915_eventid, "config:0-20"),
     803                 :            :         NULL,
     804                 :            : };
     805                 :            : 
     806                 :            : static const struct attribute_group i915_pmu_format_attr_group = {
     807                 :            :         .name = "format",
     808                 :            :         .attrs = i915_pmu_format_attrs,
     809                 :            : };
     810                 :            : 
     811                 :            : struct i915_ext_attribute {
     812                 :            :         struct device_attribute attr;
     813                 :            :         unsigned long val;
     814                 :            : };
     815                 :            : 
     816                 :          0 : static ssize_t i915_pmu_event_show(struct device *dev,
     817                 :            :                                    struct device_attribute *attr, char *buf)
     818                 :            : {
     819                 :          0 :         struct i915_ext_attribute *eattr;
     820                 :            : 
     821                 :          0 :         eattr = container_of(attr, struct i915_ext_attribute, attr);
     822                 :          0 :         return sprintf(buf, "config=0x%lx\n", eattr->val);
     823                 :            : }
     824                 :            : 
     825                 :            : static ssize_t
     826                 :          0 : i915_pmu_get_attr_cpumask(struct device *dev,
     827                 :            :                           struct device_attribute *attr,
     828                 :            :                           char *buf)
     829                 :            : {
     830                 :          0 :         return cpumap_print_to_pagebuf(true, buf, &i915_pmu_cpumask);
     831                 :            : }
     832                 :            : 
     833                 :            : static DEVICE_ATTR(cpumask, 0444, i915_pmu_get_attr_cpumask, NULL);
     834                 :            : 
     835                 :            : static struct attribute *i915_cpumask_attrs[] = {
     836                 :            :         &dev_attr_cpumask.attr,
     837                 :            :         NULL,
     838                 :            : };
     839                 :            : 
     840                 :            : static const struct attribute_group i915_pmu_cpumask_attr_group = {
     841                 :            :         .attrs = i915_cpumask_attrs,
     842                 :            : };
     843                 :            : 
     844                 :            : #define __event(__config, __name, __unit) \
     845                 :            : { \
     846                 :            :         .config = (__config), \
     847                 :            :         .name = (__name), \
     848                 :            :         .unit = (__unit), \
     849                 :            : }
     850                 :            : 
     851                 :            : #define __engine_event(__sample, __name) \
     852                 :            : { \
     853                 :            :         .sample = (__sample), \
     854                 :            :         .name = (__name), \
     855                 :            : }
     856                 :            : 
     857                 :            : static struct i915_ext_attribute *
     858                 :          0 : add_i915_attr(struct i915_ext_attribute *attr, const char *name, u64 config)
     859                 :            : {
     860                 :          0 :         sysfs_attr_init(&attr->attr.attr);
     861                 :          0 :         attr->attr.attr.name = name;
     862                 :          0 :         attr->attr.attr.mode = 0444;
     863                 :          0 :         attr->attr.show = i915_pmu_event_show;
     864                 :          0 :         attr->val = config;
     865                 :            : 
     866                 :          0 :         return ++attr;
     867                 :            : }
     868                 :            : 
     869                 :            : static struct perf_pmu_events_attr *
     870                 :          0 : add_pmu_attr(struct perf_pmu_events_attr *attr, const char *name,
     871                 :            :              const char *str)
     872                 :            : {
     873                 :          0 :         sysfs_attr_init(&attr->attr.attr);
     874                 :          0 :         attr->attr.attr.name = name;
     875                 :          0 :         attr->attr.attr.mode = 0444;
     876                 :          0 :         attr->attr.show = perf_event_sysfs_show;
     877                 :          0 :         attr->event_str = str;
     878                 :            : 
     879                 :          0 :         return ++attr;
     880                 :            : }
     881                 :            : 
     882                 :            : static struct attribute **
     883                 :          0 : create_event_attributes(struct i915_pmu *pmu)
     884                 :            : {
     885                 :          0 :         struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
     886                 :          0 :         static const struct {
     887                 :            :                 u64 config;
     888                 :            :                 const char *name;
     889                 :            :                 const char *unit;
     890                 :            :         } events[] = {
     891                 :            :                 __event(I915_PMU_ACTUAL_FREQUENCY, "actual-frequency", "M"),
     892                 :            :                 __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"),
     893                 :            :                 __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
     894                 :            :                 __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
     895                 :            :         };
     896                 :          0 :         static const struct {
     897                 :            :                 enum drm_i915_pmu_engine_sample sample;
     898                 :            :                 char *name;
     899                 :            :         } engine_events[] = {
     900                 :            :                 __engine_event(I915_SAMPLE_BUSY, "busy"),
     901                 :            :                 __engine_event(I915_SAMPLE_SEMA, "sema"),
     902                 :            :                 __engine_event(I915_SAMPLE_WAIT, "wait"),
     903                 :            :         };
     904                 :          0 :         unsigned int count = 0;
     905                 :          0 :         struct perf_pmu_events_attr *pmu_attr = NULL, *pmu_iter;
     906                 :          0 :         struct i915_ext_attribute *i915_attr = NULL, *i915_iter;
     907                 :          0 :         struct attribute **attr = NULL, **attr_iter;
     908                 :          0 :         struct intel_engine_cs *engine;
     909                 :          0 :         unsigned int i;
     910                 :            : 
     911                 :            :         /* Count how many counters we will be exposing. */
     912         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(events); i++) {
     913         [ #  # ]:          0 :                 if (!config_status(i915, events[i].config))
     914                 :          0 :                         count++;
     915                 :            :         }
     916                 :            : 
     917   [ #  #  #  #  :          0 :         for_each_uabi_engine(engine, i915) {
                   #  # ]
     918         [ #  # ]:          0 :                 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
     919      [ #  #  # ]:          0 :                         if (!engine_event_status(engine,
     920                 :            :                                                  engine_events[i].sample))
     921                 :          0 :                                 count++;
     922                 :            :                 }
     923                 :            :         }
     924                 :            : 
     925                 :            :         /* Allocate attribute objects and table. */
     926                 :          0 :         i915_attr = kcalloc(count, sizeof(*i915_attr), GFP_KERNEL);
     927         [ #  # ]:          0 :         if (!i915_attr)
     928                 :          0 :                 goto err_alloc;
     929                 :            : 
     930                 :          0 :         pmu_attr = kcalloc(count, sizeof(*pmu_attr), GFP_KERNEL);
     931         [ #  # ]:          0 :         if (!pmu_attr)
     932                 :          0 :                 goto err_alloc;
     933                 :            : 
     934                 :            :         /* Max one pointer of each attribute type plus a termination entry. */
     935                 :          0 :         attr = kcalloc(count * 2 + 1, sizeof(*attr), GFP_KERNEL);
     936         [ #  # ]:          0 :         if (!attr)
     937                 :          0 :                 goto err_alloc;
     938                 :            : 
     939                 :            :         i915_iter = i915_attr;
     940                 :            :         pmu_iter = pmu_attr;
     941                 :            :         attr_iter = attr;
     942                 :            : 
     943                 :            :         /* Initialize supported non-engine counters. */
     944         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(events); i++) {
     945                 :          0 :                 char *str;
     946                 :            : 
     947         [ #  # ]:          0 :                 if (config_status(i915, events[i].config))
     948                 :          0 :                         continue;
     949                 :            : 
     950                 :          0 :                 str = kstrdup(events[i].name, GFP_KERNEL);
     951         [ #  # ]:          0 :                 if (!str)
     952                 :          0 :                         goto err;
     953                 :            : 
     954                 :          0 :                 *attr_iter++ = &i915_iter->attr.attr;
     955                 :          0 :                 i915_iter = add_i915_attr(i915_iter, str, events[i].config);
     956                 :            : 
     957         [ #  # ]:          0 :                 if (events[i].unit) {
     958                 :          0 :                         str = kasprintf(GFP_KERNEL, "%s.unit", events[i].name);
     959         [ #  # ]:          0 :                         if (!str)
     960                 :          0 :                                 goto err;
     961                 :            : 
     962                 :          0 :                         *attr_iter++ = &pmu_iter->attr.attr;
     963                 :          0 :                         pmu_iter = add_pmu_attr(pmu_iter, str, events[i].unit);
     964                 :            :                 }
     965                 :            :         }
     966                 :            : 
     967                 :            :         /* Initialize supported engine counters. */
     968   [ #  #  #  #  :          0 :         for_each_uabi_engine(engine, i915) {
                   #  # ]
     969         [ #  # ]:          0 :                 for (i = 0; i < ARRAY_SIZE(engine_events); i++) {
     970                 :          0 :                         char *str;
     971                 :            : 
     972      [ #  #  # ]:          0 :                         if (engine_event_status(engine,
     973                 :            :                                                 engine_events[i].sample))
     974                 :          0 :                                 continue;
     975                 :            : 
     976                 :          0 :                         str = kasprintf(GFP_KERNEL, "%s-%s",
     977                 :          0 :                                         engine->name, engine_events[i].name);
     978         [ #  # ]:          0 :                         if (!str)
     979                 :          0 :                                 goto err;
     980                 :            : 
     981                 :          0 :                         *attr_iter++ = &i915_iter->attr.attr;
     982                 :          0 :                         i915_iter =
     983                 :          0 :                                 add_i915_attr(i915_iter, str,
     984                 :          0 :                                               __I915_PMU_ENGINE(engine->uabi_class,
     985                 :            :                                                                 engine->uabi_instance,
     986                 :            :                                                                 engine_events[i].sample));
     987                 :            : 
     988                 :          0 :                         str = kasprintf(GFP_KERNEL, "%s-%s.unit",
     989                 :            :                                         engine->name, engine_events[i].name);
     990         [ #  # ]:          0 :                         if (!str)
     991                 :          0 :                                 goto err;
     992                 :            : 
     993                 :          0 :                         *attr_iter++ = &pmu_iter->attr.attr;
     994                 :          0 :                         pmu_iter = add_pmu_attr(pmu_iter, str, "ns");
     995                 :            :                 }
     996                 :            :         }
     997                 :            : 
     998                 :          0 :         pmu->i915_attr = i915_attr;
     999                 :          0 :         pmu->pmu_attr = pmu_attr;
    1000                 :            : 
    1001                 :          0 :         return attr;
    1002                 :            : 
    1003                 :            : err:;
    1004         [ #  # ]:          0 :         for (attr_iter = attr; *attr_iter; attr_iter++)
    1005                 :          0 :                 kfree((*attr_iter)->name);
    1006                 :            : 
    1007                 :          0 : err_alloc:
    1008                 :          0 :         kfree(attr);
    1009                 :          0 :         kfree(i915_attr);
    1010                 :          0 :         kfree(pmu_attr);
    1011                 :            : 
    1012                 :          0 :         return NULL;
    1013                 :            : }
    1014                 :            : 
    1015                 :          0 : static void free_event_attributes(struct i915_pmu *pmu)
    1016                 :            : {
    1017                 :          0 :         struct attribute **attr_iter = pmu->events_attr_group.attrs;
    1018                 :            : 
    1019         [ #  # ]:          0 :         for (; *attr_iter; attr_iter++)
    1020                 :          0 :                 kfree((*attr_iter)->name);
    1021                 :            : 
    1022                 :          0 :         kfree(pmu->events_attr_group.attrs);
    1023                 :          0 :         kfree(pmu->i915_attr);
    1024                 :          0 :         kfree(pmu->pmu_attr);
    1025                 :            : 
    1026                 :          0 :         pmu->events_attr_group.attrs = NULL;
    1027                 :          0 :         pmu->i915_attr = NULL;
    1028                 :          0 :         pmu->pmu_attr = NULL;
    1029                 :          0 : }
    1030                 :            : 
    1031                 :          0 : static int i915_pmu_cpu_online(unsigned int cpu, struct hlist_node *node)
    1032                 :            : {
    1033                 :          0 :         struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
    1034                 :            : 
    1035                 :          0 :         GEM_BUG_ON(!pmu->base.event_init);
    1036                 :            : 
    1037                 :            :         /* Select the first online CPU as a designated reader. */
    1038         [ #  # ]:          0 :         if (!cpumask_weight(&i915_pmu_cpumask))
    1039                 :          0 :                 cpumask_set_cpu(cpu, &i915_pmu_cpumask);
    1040                 :            : 
    1041                 :          0 :         return 0;
    1042                 :            : }
    1043                 :            : 
    1044                 :          0 : static int i915_pmu_cpu_offline(unsigned int cpu, struct hlist_node *node)
    1045                 :            : {
    1046         [ #  # ]:          0 :         struct i915_pmu *pmu = hlist_entry_safe(node, typeof(*pmu), cpuhp.node);
    1047                 :          0 :         unsigned int target;
    1048                 :            : 
    1049                 :          0 :         GEM_BUG_ON(!pmu->base.event_init);
    1050                 :            : 
    1051         [ #  # ]:          0 :         if (cpumask_test_and_clear_cpu(cpu, &i915_pmu_cpumask)) {
    1052                 :          0 :                 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
    1053                 :            :                 /* Migrate events if there is a valid target */
    1054         [ #  # ]:          0 :                 if (target < nr_cpu_ids) {
    1055                 :          0 :                         cpumask_set_cpu(target, &i915_pmu_cpumask);
    1056                 :          0 :                         perf_pmu_migrate_context(&pmu->base, cpu, target);
    1057                 :            :                 }
    1058                 :            :         }
    1059                 :            : 
    1060                 :          0 :         return 0;
    1061                 :            : }
    1062                 :            : 
    1063                 :          0 : static int i915_pmu_register_cpuhp_state(struct i915_pmu *pmu)
    1064                 :            : {
    1065                 :          0 :         enum cpuhp_state slot;
    1066                 :          0 :         int ret;
    1067                 :            : 
    1068                 :          0 :         ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN,
    1069                 :            :                                       "perf/x86/intel/i915:online",
    1070                 :            :                                       i915_pmu_cpu_online,
    1071                 :            :                                       i915_pmu_cpu_offline);
    1072         [ #  # ]:          0 :         if (ret < 0)
    1073                 :            :                 return ret;
    1074                 :            : 
    1075                 :          0 :         slot = ret;
    1076                 :          0 :         ret = cpuhp_state_add_instance(slot, &pmu->cpuhp.node);
    1077         [ #  # ]:          0 :         if (ret) {
    1078                 :          0 :                 cpuhp_remove_multi_state(slot);
    1079                 :          0 :                 return ret;
    1080                 :            :         }
    1081                 :            : 
    1082                 :          0 :         pmu->cpuhp.slot = slot;
    1083                 :          0 :         return 0;
    1084                 :            : }
    1085                 :            : 
    1086                 :          0 : static void i915_pmu_unregister_cpuhp_state(struct i915_pmu *pmu)
    1087                 :            : {
    1088         [ #  # ]:          0 :         WARN_ON(pmu->cpuhp.slot == CPUHP_INVALID);
    1089         [ #  # ]:          0 :         WARN_ON(cpuhp_state_remove_instance(pmu->cpuhp.slot, &pmu->cpuhp.node));
    1090                 :          0 :         cpuhp_remove_multi_state(pmu->cpuhp.slot);
    1091                 :          0 :         pmu->cpuhp.slot = CPUHP_INVALID;
    1092                 :          0 : }
    1093                 :            : 
    1094                 :          0 : static bool is_igp(struct drm_i915_private *i915)
    1095                 :            : {
    1096                 :          0 :         struct pci_dev *pdev = i915->drm.pdev;
    1097                 :            : 
    1098                 :            :         /* IGP is 0000:00:02.0 */
    1099                 :          0 :         return pci_domain_nr(pdev->bus) == 0 &&
    1100   [ #  #  #  #  :          0 :                pdev->bus->number == 0 &&
                   #  # ]
    1101   [ #  #  #  #  :          0 :                PCI_SLOT(pdev->devfn) == 2 &&
          #  #  #  #  #  
                #  #  # ]
    1102   [ #  #  #  #  :          0 :                PCI_FUNC(pdev->devfn) == 0;
                   #  # ]
    1103                 :            : }
    1104                 :            : 
    1105                 :          0 : void i915_pmu_register(struct drm_i915_private *i915)
    1106                 :            : {
    1107                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
    1108                 :          0 :         const struct attribute_group *attr_groups[] = {
    1109                 :            :                 &i915_pmu_format_attr_group,
    1110                 :          0 :                 &pmu->events_attr_group,
    1111                 :            :                 &i915_pmu_cpumask_attr_group,
    1112                 :            :                 NULL
    1113                 :            :         };
    1114                 :            : 
    1115                 :          0 :         int ret = -ENOMEM;
    1116                 :            : 
    1117         [ #  # ]:          0 :         if (INTEL_GEN(i915) <= 2) {
    1118                 :          0 :                 dev_info(i915->drm.dev, "PMU not supported for this GPU.");
    1119                 :          0 :                 return;
    1120                 :            :         }
    1121                 :            : 
    1122                 :          0 :         spin_lock_init(&pmu->lock);
    1123                 :          0 :         hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    1124                 :          0 :         pmu->timer.function = i915_sample;
    1125                 :          0 :         pmu->cpuhp.slot = CPUHP_INVALID;
    1126                 :            : 
    1127   [ #  #  #  # ]:          0 :         if (!is_igp(i915)) {
    1128                 :          0 :                 pmu->name = kasprintf(GFP_KERNEL,
    1129                 :            :                                       "i915_%s",
    1130         [ #  # ]:          0 :                                       dev_name(i915->drm.dev));
    1131         [ #  # ]:          0 :                 if (pmu->name) {
    1132                 :            :                         /* tools/perf reserves colons as special. */
    1133                 :          0 :                         strreplace((char *)pmu->name, ':', '_');
    1134                 :            :                 }
    1135                 :            :         } else {
    1136                 :          0 :                 pmu->name = "i915";
    1137                 :            :         }
    1138         [ #  # ]:          0 :         if (!pmu->name)
    1139                 :          0 :                 goto err;
    1140                 :            : 
    1141                 :          0 :         pmu->events_attr_group.name = "events";
    1142                 :          0 :         pmu->events_attr_group.attrs = create_event_attributes(pmu);
    1143         [ #  # ]:          0 :         if (!pmu->events_attr_group.attrs)
    1144                 :          0 :                 goto err_name;
    1145                 :            : 
    1146                 :          0 :         pmu->base.attr_groups = kmemdup(attr_groups, sizeof(attr_groups),
    1147                 :            :                                         GFP_KERNEL);
    1148         [ #  # ]:          0 :         if (!pmu->base.attr_groups)
    1149                 :          0 :                 goto err_attr;
    1150                 :            : 
    1151                 :          0 :         pmu->base.task_ctx_nr        = perf_invalid_context;
    1152                 :          0 :         pmu->base.event_init = i915_pmu_event_init;
    1153                 :          0 :         pmu->base.add                = i915_pmu_event_add;
    1154                 :          0 :         pmu->base.del                = i915_pmu_event_del;
    1155                 :          0 :         pmu->base.start              = i915_pmu_event_start;
    1156                 :          0 :         pmu->base.stop               = i915_pmu_event_stop;
    1157                 :          0 :         pmu->base.read               = i915_pmu_event_read;
    1158                 :          0 :         pmu->base.event_idx  = i915_pmu_event_event_idx;
    1159                 :            : 
    1160                 :          0 :         ret = perf_pmu_register(&pmu->base, pmu->name, -1);
    1161         [ #  # ]:          0 :         if (ret)
    1162                 :          0 :                 goto err_groups;
    1163                 :            : 
    1164                 :          0 :         ret = i915_pmu_register_cpuhp_state(pmu);
    1165         [ #  # ]:          0 :         if (ret)
    1166                 :          0 :                 goto err_unreg;
    1167                 :            : 
    1168                 :            :         return;
    1169                 :            : 
    1170                 :            : err_unreg:
    1171                 :          0 :         perf_pmu_unregister(&pmu->base);
    1172                 :          0 : err_groups:
    1173                 :          0 :         kfree(pmu->base.attr_groups);
    1174                 :          0 : err_attr:
    1175                 :          0 :         pmu->base.event_init = NULL;
    1176                 :          0 :         free_event_attributes(pmu);
    1177                 :          0 : err_name:
    1178   [ #  #  #  # ]:          0 :         if (!is_igp(i915))
    1179                 :          0 :                 kfree(pmu->name);
    1180                 :          0 : err:
    1181                 :          0 :         dev_notice(i915->drm.dev, "Failed to register PMU!\n");
    1182                 :            : }
    1183                 :            : 
    1184                 :          0 : void i915_pmu_unregister(struct drm_i915_private *i915)
    1185                 :            : {
    1186                 :          0 :         struct i915_pmu *pmu = &i915->pmu;
    1187                 :            : 
    1188         [ #  # ]:          0 :         if (!pmu->base.event_init)
    1189                 :            :                 return;
    1190                 :            : 
    1191         [ #  # ]:          0 :         WARN_ON(pmu->enable);
    1192                 :            : 
    1193                 :          0 :         hrtimer_cancel(&pmu->timer);
    1194                 :            : 
    1195                 :          0 :         i915_pmu_unregister_cpuhp_state(pmu);
    1196                 :            : 
    1197                 :          0 :         perf_pmu_unregister(&pmu->base);
    1198                 :          0 :         pmu->base.event_init = NULL;
    1199                 :          0 :         kfree(pmu->base.attr_groups);
    1200   [ #  #  #  # ]:          0 :         if (!is_igp(i915))
    1201                 :          0 :                 kfree(pmu->name);
    1202                 :          0 :         free_event_attributes(pmu);
    1203                 :            : }

Generated by: LCOV version 1.14