Re: [PATCH 05/15] drm/panfrost: use spinlock instead of atomic
Hi Robin, On Fri, 29 May 2020 at 14:20, Robin Murphy wrote: > > On 2020-05-10 17:55, Clément Péron wrote: > > Convert busy_count to a simple int protected by spinlock. > > A little more reasoning might be nice. I have follow the modification requested for lima devfreq and clearly don't have any argument to switch to spinlock. The Lima Maintainer asked to change witht the following reason : "Better make this count a normal int which is also protected by the spinlock, because current implementation can't protect atomic ops for state change and busy idle check and we are using spinlock already" > > > Signed-off-by: Clément Péron > > --- > [...] > > diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h > > b/drivers/gpu/drm/panfrost/panfrost_devfreq.h > > index 0697f8d5aa34..e6629900a618 100644 > > --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h > > +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h > > @@ -4,6 +4,7 @@ > > #ifndef __PANFROST_DEVFREQ_H__ > > #define __PANFROST_DEVFREQ_H__ > > > > +#include > > #include > > > > struct devfreq; > > @@ -14,10 +15,17 @@ struct panfrost_device; > > struct panfrost_devfreq { > > struct devfreq *devfreq; > > struct thermal_cooling_device *cooling; > > + > > ktime_t busy_time; > > ktime_t idle_time; > > ktime_t time_last_update; > > - atomic_t busy_count; > > + int busy_count; > > + /* > > + * Protect busy_time, idle_time, time_last_update and busy_count > > + * because these can be updated concurrently, for example by the GP > > + * and PP interrupts. > > + */ > > Nit: this comment is clearly wrong, since we only have Job, GPU and MMU > interrupts here. I guess if there is a race it would be between > submission/completion/timeout on different job slots. It's copy/paste from lima I will update it, > > Given that, should this actually be considered a fix for 9e62b885f715 > ("drm/panfrost: Simplify devfreq utilisation tracking")? I can't say if it can be considered as a fix, I didn't see any improvement on my board before and after this patch. I'm still facing some issue and didn't have time to fully investigate it. Thanks for you review, > > Robin. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 05/15] drm/panfrost: use spinlock instead of atomic
On 29/05/2020 13:35, Clément Péron wrote: Hi Robin, On Fri, 29 May 2020 at 14:20, Robin Murphy wrote: On 2020-05-10 17:55, Clément Péron wrote: Convert busy_count to a simple int protected by spinlock. A little more reasoning might be nice. I have follow the modification requested for lima devfreq and clearly don't have any argument to switch to spinlock. The Lima Maintainer asked to change witht the following reason : "Better make this count a normal int which is also protected by the spinlock, because current implementation can't protect atomic ops for state change and busy idle check and we are using spinlock already" Signed-off-by: Clément Péron --- [...] diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 0697f8d5aa34..e6629900a618 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -4,6 +4,7 @@ #ifndef __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__ +#include #include struct devfreq; @@ -14,10 +15,17 @@ struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; struct thermal_cooling_device *cooling; + ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; - atomic_t busy_count; + int busy_count; + /* + * Protect busy_time, idle_time, time_last_update and busy_count + * because these can be updated concurrently, for example by the GP + * and PP interrupts. + */ Nit: this comment is clearly wrong, since we only have Job, GPU and MMU interrupts here. I guess if there is a race it would be between submission/completion/timeout on different job slots. It's copy/paste from lima I will update it, Lima ('Utgard') has separate units for geometry and pixel processing (GP/PP). For Panfrost ('Midgard'/'Bifrost') we don't have that separation, however there are multiple job slots. which are implemented as multiple DRM schedulers. So the same fix is appropriate, but clearly I missed this comment because it's referring to GP/PP which don't exist for Midgard/Bifrost. Given that, should this actually be considered a fix for 9e62b885f715 ("drm/panfrost: Simplify devfreq utilisation tracking")? I can't say if it can be considered as a fix, I didn't see any improvement on my board before and after this patch. I'm still facing some issue and didn't have time to fully investigate it. Technically this is a fix - there's a small race which could cause the devfreq information to become corrupted. However it would resolve itself on the next devfreq interval when panfrost_devfreq_reset() is called. So the impact is very minor (devfreq gets some bogus figures). The important variable (busy_count) was already an atomic so won't be affected. Steve Thanks for you review, Robin. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 05/15] drm/panfrost: use spinlock instead of atomic
On 2020-05-10 17:55, Clément Péron wrote: Convert busy_count to a simple int protected by spinlock. A little more reasoning might be nice. Signed-off-by: Clément Péron --- [...] diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 0697f8d5aa34..e6629900a618 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -4,6 +4,7 @@ #ifndef __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__ +#include #include struct devfreq; @@ -14,10 +15,17 @@ struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; struct thermal_cooling_device *cooling; + ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; - atomic_t busy_count; + int busy_count; + /* +* Protect busy_time, idle_time, time_last_update and busy_count +* because these can be updated concurrently, for example by the GP +* and PP interrupts. +*/ Nit: this comment is clearly wrong, since we only have Job, GPU and MMU interrupts here. I guess if there is a race it would be between submission/completion/timeout on different job slots. Given that, should this actually be considered a fix for 9e62b885f715 ("drm/panfrost: Simplify devfreq utilisation tracking")? Robin. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 05/15] drm/panfrost: use spinlock instead of atomic
On 10/05/2020 17:55, Clément Péron wrote: Convert busy_count to a simple int protected by spinlock. Signed-off-by: Clément Péron Looks like a fairly mechanical cleanup. Reviewed-by: Steven Price --- drivers/gpu/drm/panfrost/panfrost_devfreq.c | 43 +++-- drivers/gpu/drm/panfrost/panfrost_devfreq.h | 10 - 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 962550363391..78753cfb59fb 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -12,16 +12,12 @@ static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) { - ktime_t now; - ktime_t last; - - if (!pfdevfreq->devfreq) - return; + ktime_t now, last; now = ktime_get(); last = pfdevfreq->time_last_update; - if (atomic_read(>busy_count) > 0) + if (pfdevfreq->busy_count > 0) pfdevfreq->busy_time += ktime_sub(now, last); else pfdevfreq->idle_time += ktime_sub(now, last); @@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, { struct panfrost_device *pfdev = dev_get_drvdata(dev); struct panfrost_devfreq *pfdevfreq = >pfdevfreq; + unsigned long irqflags; + + status->current_frequency = clk_get_rate(pfdev->clock); + + spin_lock_irqsave(>lock, irqflags); panfrost_devfreq_update_utilization(pfdevfreq); - status->current_frequency = clk_get_rate(pfdev->clock); status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, pfdevfreq->idle_time)); @@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, panfrost_devfreq_reset(pfdevfreq); + spin_unlock_irqrestore(>lock, irqflags); + dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", status->busy_time, status->total_time, status->busy_time / (status->total_time / 100), @@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) else if (ret) return ret; + spin_lock_init(>lock); + panfrost_devfreq_reset(pfdevfreq); cur_freq = clk_get_rate(pfdev->clock); @@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) { + unsigned long irqflags; + + if (!pfdevfreq->devfreq) + return; + + spin_lock_irqsave(>lock, irqflags); + panfrost_devfreq_update_utilization(pfdevfreq); - atomic_inc(>busy_count); + + pfdevfreq->busy_count++; + + spin_unlock_irqrestore(>lock, irqflags); } void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) { - int count; + unsigned long irqflags; + + if (!pfdevfreq->devfreq) + return; + + spin_lock_irqsave(>lock, irqflags); panfrost_devfreq_update_utilization(pfdevfreq); - count = atomic_dec_if_positive(>busy_count); - WARN_ON(count < 0); + + WARN_ON(--pfdevfreq->busy_count < 0); + + spin_unlock_irqrestore(>lock, irqflags); } diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h index 0697f8d5aa34..e6629900a618 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.h +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.h @@ -4,6 +4,7 @@ #ifndef __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__ +#include #include struct devfreq; @@ -14,10 +15,17 @@ struct panfrost_device; struct panfrost_devfreq { struct devfreq *devfreq; struct thermal_cooling_device *cooling; + ktime_t busy_time; ktime_t idle_time; ktime_t time_last_update; - atomic_t busy_count; + int busy_count; + /* +* Protect busy_time, idle_time, time_last_update and busy_count +* because these can be updated concurrently, for example by the GP +* and PP interrupts. +*/ + spinlock_t lock; }; int panfrost_devfreq_init(struct panfrost_device *pfdev); ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel