Skip to content

Commit 9c6508b

Browse files
committed
drm/i915/pmu: Replace open coded kstat_irqs() copy
Driver code has no business with the internals of the irq descriptor. Aside of that the count is per interrupt line and therefore takes interrupts from other devices into account which share the interrupt line and are not handled by the graphics driver. Replace it with a pmu private count which only counts interrupts which originate from the graphics card. To avoid atomics or heuristics of some sort make the counter field 'unsigned long'. That limits the count to 4e9 on 32bit which is a lot and postprocessing can easily deal with the occasional wraparound. Signed-off-by: Thomas Gleixner <[email protected]> Acked-by: Jani Nikula <[email protected]> Cc: Tvrtko Ursulin <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3afba09 commit 9c6508b

File tree

3 files changed

+43
-18
lines changed

3 files changed

+43
-18
lines changed

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,24 @@
6060
* and related files, but that will be described in separate chapters.
6161
*/
6262

63+
/*
64+
* Interrupt statistic for PMU. Increments the counter only if the
65+
* interrupt originated from the the GPU so interrupts from a device which
66+
* shares the interrupt line are not accounted.
67+
*/
68+
static inline void pmu_irq_stats(struct drm_i915_private *i915,
69+
irqreturn_t res)
70+
{
71+
if (unlikely(res != IRQ_HANDLED))
72+
return;
73+
74+
/*
75+
* A clever compiler translates that into INC. A not so clever one
76+
* should at least prevent store tearing.
77+
*/
78+
WRITE_ONCE(i915->pmu.irq_count, i915->pmu.irq_count + 1);
79+
}
80+
6381
typedef bool (*long_pulse_detect_func)(enum hpd_pin pin, u32 val);
6482

6583
static const u32 hpd_ilk[HPD_NUM_PINS] = {
@@ -1599,6 +1617,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
15991617
valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
16001618
} while (0);
16011619

1620+
pmu_irq_stats(dev_priv, ret);
1621+
16021622
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
16031623

16041624
return ret;
@@ -1676,6 +1696,8 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
16761696
valleyview_pipestat_irq_handler(dev_priv, pipe_stats);
16771697
} while (0);
16781698

1699+
pmu_irq_stats(dev_priv, ret);
1700+
16791701
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
16801702

16811703
return ret;
@@ -2103,6 +2125,8 @@ static irqreturn_t ilk_irq_handler(int irq, void *arg)
21032125
if (sde_ier)
21042126
raw_reg_write(regs, SDEIER, sde_ier);
21052127

2128+
pmu_irq_stats(i915, ret);
2129+
21062130
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
21072131
enable_rpm_wakeref_asserts(&i915->runtime_pm);
21082132

@@ -2419,6 +2443,8 @@ static irqreturn_t gen8_irq_handler(int irq, void *arg)
24192443

24202444
gen8_master_intr_enable(regs);
24212445

2446+
pmu_irq_stats(dev_priv, IRQ_HANDLED);
2447+
24222448
return IRQ_HANDLED;
24232449
}
24242450

@@ -2514,6 +2540,8 @@ __gen11_irq_handler(struct drm_i915_private * const i915,
25142540

25152541
gen11_gu_misc_irq_handler(gt, gu_misc_iir);
25162542

2543+
pmu_irq_stats(i915, IRQ_HANDLED);
2544+
25172545
return IRQ_HANDLED;
25182546
}
25192547

@@ -3688,6 +3716,8 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
36883716
i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats);
36893717
} while (0);
36903718

3719+
pmu_irq_stats(dev_priv, ret);
3720+
36913721
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
36923722

36933723
return ret;
@@ -3796,6 +3826,8 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
37963826
i915_pipestat_irq_handler(dev_priv, iir, pipe_stats);
37973827
} while (0);
37983828

3829+
pmu_irq_stats(dev_priv, ret);
3830+
37993831
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
38003832

38013833
return ret;
@@ -3941,6 +3973,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
39413973
i965_pipestat_irq_handler(dev_priv, iir, pipe_stats);
39423974
} while (0);
39433975

3976+
pmu_irq_stats(dev_priv, IRQ_HANDLED);
3977+
39443978
enable_rpm_wakeref_asserts(&dev_priv->runtime_pm);
39453979

39463980
return ret;

drivers/gpu/drm/i915/i915_pmu.c

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
* Copyright © 2017-2018 Intel Corporation
55
*/
66

7-
#include <linux/irq.h>
87
#include <linux/pm_runtime.h>
98

109
#include "gt/intel_engine.h"
@@ -423,22 +422,6 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer)
423422
return HRTIMER_RESTART;
424423
}
425424

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-
442425
static void i915_pmu_event_destroy(struct perf_event *event)
443426
{
444427
struct drm_i915_private *i915 =
@@ -581,7 +564,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
581564
USEC_PER_SEC /* to MHz */);
582565
break;
583566
case I915_PMU_INTERRUPTS:
584-
val = count_interrupts(i915);
567+
val = READ_ONCE(pmu->irq_count);
585568
break;
586569
case I915_PMU_RC6_RESIDENCY:
587570
val = get_rc6(&i915->gt);

drivers/gpu/drm/i915/i915_pmu.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ struct i915_pmu {
107107
* @sleep_last: Last time GT parked for RC6 estimation.
108108
*/
109109
ktime_t sleep_last;
110+
/**
111+
* @irq_count: Number of interrupts
112+
*
113+
* Intentionally unsigned long to avoid atomics or heuristics on 32bit.
114+
* 4e9 interrupts are a lot and postprocessing can really deal with an
115+
* occasional wraparound easily. It's 32bit after all.
116+
*/
117+
unsigned long irq_count;
110118
/**
111119
* @events_attr_group: Device events attribute group.
112120
*/

0 commit comments

Comments
 (0)