[patch 14/30] drm/i915/pmu: Replace open coded kstat_irqs() copy
Thomas Gleixner
tglx at linutronix.de
Fri Dec 11 12:57:49 UTC 2020
On Fri, Dec 11 2020 at 10:13, Tvrtko Ursulin wrote:
> On 10/12/2020 19:25, Thomas Gleixner wrote:
>>
>> 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.
>
> After my failed hasty sketch from last night I had a different one which
> was kind of heuristics based (re-reading the upper dword and retrying if
> it changed on 32-bit).
The problem is that there will be two seperate modifications for the low
and high word. Several ways how the compiler can translate this, but the
problem is the same for all of them:
CPU 0 CPU 1
load low
load high
add low, 1
addc high, 0
store low load high
--> NMI load low
load high and compare
store high
You can't catch that. If this really becomes an issue you need a
sequence counter around it.
> But you are right - it is okay to at least start
> like this today and if later there is a need we can either do that or
> deal with wrap at PMU read time.
Right.
>> +/*
>> + * Interrupt statistic for PMU. Increments the counter only if the
>> + * interrupt originated from the the GPU so interrupts from a device which
>> + * shares the interrupt line are not accounted.
>> + */
>> +static inline void pmu_irq_stats(struct drm_i915_private *priv,
>
> We never use priv as a local name, it should be either i915 or
> dev_priv.
Sure, will fix.
>> + /*
>> + * A clever compiler translates that into INC. A not so clever one
>> + * should at least prevent store tearing.
>> + */
>> + WRITE_ONCE(priv->pmu.irq_count, priv->pmu.irq_count + 1);
>
> Curious, probably more educational for me - given x86_32 and x86_64, and
> the context of it getting called, what is the difference from just doing
> irq_count++?
Several reasons:
1) The compiler can pretty much do what it wants with cnt++
including tearing and whatever. https://lwn.net/Articles/816850/
for the full set of insanities.
Not really a problem here, but
2) It's annotating the reader and the writer side and documenting
that this is subject to concurrency
3) It will prevent KCSAN to complain about the data race,
i.e. concurrent modification while reading.
Thanks,
tglx
>> --- a/drivers/gpu/drm/i915/i915_pmu.c
>> +++ b/drivers/gpu/drm/i915/i915_pmu.c
>> @@ -423,22 +423,6 @@ static enum hrtimer_restart i915_sample(
>> return HRTIMER_RESTART;
>> }
>
> In this file you can also drop the #include <linux/irq.h> line.
Indeed.
Thanks,
tglx
More information about the dri-devel
mailing list