summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/panfrost
diff options
context:
space:
mode:
authorClément Péron <peron.clem@gmail.com>2020-07-10 11:54:00 +0200
committerRob Herring <robh@kernel.org>2020-08-07 10:11:26 -0600
commited85df3f60740bb4be23fbc2db283d59b361a834 (patch)
treecdc3736b348bdab97456effcd549f5539e3a5a89 /drivers/gpu/drm/panfrost
parent9bfacfc82f903b066b0b63460d5b7943705048a4 (diff)
drm/panfrost: use spinlock instead of atomic
Convert busy_count to a simple int protected by spinlock. Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Signed-off-by: Clément Péron <peron.clem@gmail.com> Signed-off-by: Rob Herring <robh@kernel.org> Link: https://patchwork.freedesktop.org/patch/msgid/20200710095409.407087-6-peron.clem@gmail.com
Diffstat (limited to 'drivers/gpu/drm/panfrost')
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.c43
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_devfreq.h9
2 files changed, 40 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(&pfdevfreq->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 = &pfdev->pfdevfreq;
+ unsigned long irqflags;
+
+ status->current_frequency = clk_get_rate(pfdev->clock);
+
+ spin_lock_irqsave(&pfdevfreq->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(&pfdevfreq->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(&pfdevfreq->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(&pfdevfreq->lock, irqflags);
+
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)
{
- int count;
+ unsigned long irqflags;
+
+ if (!pfdevfreq->devfreq)
+ return;
+
+ spin_lock_irqsave(&pfdevfreq->lock, irqflags);
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);
}
diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.h b/drivers/gpu/drm/panfrost/panfrost_devfreq.h
index 0697f8d5aa34..3392df1020be 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 <linux/spinlock.h>
#include <linux/ktime.h>
struct devfreq;
@@ -14,10 +15,16 @@ 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 between multiple jobs.
+ */
+ spinlock_t lock;
};
int panfrost_devfreq_init(struct panfrost_device *pfdev);