Commit ed85df3f authored by Clément Péron's avatar Clément Péron Committed by Rob Herring

drm/panfrost: use spinlock instead of atomic

Convert busy_count to a simple int protected by spinlock.
Reviewed-by: default avatarSteven Price <steven.price@arm.com>
Reviewed-by: default avatarAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Signed-off-by: default avatarClément Péron <peron.clem@gmail.com>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-6-peron.clem@gmail.com
parent 9bfacfc8
...@@ -12,16 +12,12 @@ ...@@ -12,16 +12,12 @@
static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq) static void panfrost_devfreq_update_utilization(struct panfrost_devfreq *pfdevfreq)
{ {
ktime_t now; ktime_t now, last;
ktime_t last;
if (!pfdevfreq->devfreq)
return;
now = ktime_get(); now = ktime_get();
last = pfdevfreq->time_last_update; last = pfdevfreq->time_last_update;
if (atomic_read(&pfdevfreq->busy_count) > 0) if (pfdevfreq->busy_count > 0)
pfdevfreq->busy_time += ktime_sub(now, last); pfdevfreq->busy_time += ktime_sub(now, last);
else else
pfdevfreq->idle_time += ktime_sub(now, last); pfdevfreq->idle_time += ktime_sub(now, last);
...@@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, ...@@ -59,10 +55,14 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
{ {
struct panfrost_device *pfdev = dev_get_drvdata(dev); struct panfrost_device *pfdev = dev_get_drvdata(dev);
struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq; struct panfrost_devfreq *pfdevfreq = &pfdev->pfdevfreq;
unsigned long irqflags;
status->current_frequency = clk_get_rate(pfdev->clock);
spin_lock_irqsave(&pfdevfreq->lock, irqflags);
panfrost_devfreq_update_utilization(pfdevfreq); panfrost_devfreq_update_utilization(pfdevfreq);
status->current_frequency = clk_get_rate(pfdev->clock);
status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time, status->total_time = ktime_to_ns(ktime_add(pfdevfreq->busy_time,
pfdevfreq->idle_time)); pfdevfreq->idle_time));
...@@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev, ...@@ -70,6 +70,8 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
panfrost_devfreq_reset(pfdevfreq); panfrost_devfreq_reset(pfdevfreq);
spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
dev_dbg(pfdev->dev, "busy %lu total %lu %lu %% freq %lu MHz\n", 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,
status->busy_time / (status->total_time / 100), status->busy_time / (status->total_time / 100),
...@@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) ...@@ -100,6 +102,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev)
else if (ret) else if (ret)
return ret; return ret;
spin_lock_init(&pfdevfreq->lock);
panfrost_devfreq_reset(pfdevfreq); panfrost_devfreq_reset(pfdevfreq);
cur_freq = clk_get_rate(pfdev->clock); cur_freq = clk_get_rate(pfdev->clock);
...@@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev) ...@@ -162,15 +166,32 @@ void panfrost_devfreq_suspend(struct panfrost_device *pfdev)
void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq) void panfrost_devfreq_record_busy(struct panfrost_devfreq *pfdevfreq)
{ {
unsigned long irqflags;
if (!pfdevfreq->devfreq)
return;
spin_lock_irqsave(&pfdevfreq->lock, irqflags);
panfrost_devfreq_update_utilization(pfdevfreq); panfrost_devfreq_update_utilization(pfdevfreq);
atomic_inc(&pfdevfreq->busy_count);
pfdevfreq->busy_count++;
spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
} }
void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq) void panfrost_devfreq_record_idle(struct panfrost_devfreq *pfdevfreq)
{ {
int count; unsigned long irqflags;
if (!pfdevfreq->devfreq)
return;
spin_lock_irqsave(&pfdevfreq->lock, irqflags);
panfrost_devfreq_update_utilization(pfdevfreq); panfrost_devfreq_update_utilization(pfdevfreq);
count = atomic_dec_if_positive(&pfdevfreq->busy_count);
WARN_ON(count < 0); WARN_ON(--pfdevfreq->busy_count < 0);
spin_unlock_irqrestore(&pfdevfreq->lock, irqflags);
} }
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#ifndef __PANFROST_DEVFREQ_H__ #ifndef __PANFROST_DEVFREQ_H__
#define __PANFROST_DEVFREQ_H__ #define __PANFROST_DEVFREQ_H__
#include <linux/spinlock.h>
#include <linux/ktime.h> #include <linux/ktime.h>
struct devfreq; struct devfreq;
...@@ -14,10 +15,16 @@ struct panfrost_device; ...@@ -14,10 +15,16 @@ struct panfrost_device;
struct panfrost_devfreq { struct panfrost_devfreq {
struct devfreq *devfreq; struct devfreq *devfreq;
struct thermal_cooling_device *cooling; struct thermal_cooling_device *cooling;
ktime_t busy_time; ktime_t busy_time;
ktime_t idle_time; ktime_t idle_time;
ktime_t time_last_update; 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 between multiple jobs.
*/
spinlock_t lock;
}; };
int panfrost_devfreq_init(struct panfrost_device *pfdev); int panfrost_devfreq_init(struct panfrost_device *pfdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment