mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
drm/panfrost: Replace fdinfo's profiling debugfs knob with sysfs
Debugfs isn't always available in production builds that try to squeeze every single byte out of the kernel image, but we still need a way to toggle the timestamp and cycle counter registers so that jobs can be profiled for fdinfo's drm engine and cycle calculations. Drop the debugfs knob and replace it with a sysfs file that accomplishes the same functionality, and document its ABI in a separate file. Signed-off-by: Adrián Larumbe <adrian.larumbe@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Link: https://patchwork.freedesktop.org/patch/msgid/20240306015819.822128-2-adrian.larumbe@collabora.com
This commit is contained in:
parent
57a4e3a94c
commit
b12f3ea7c1
10
Documentation/ABI/testing/sysfs-driver-panfrost-profiling
Normal file
10
Documentation/ABI/testing/sysfs-driver-panfrost-profiling
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
What: /sys/bus/platform/drivers/panfrost/.../profiling
|
||||||
|
Date: February 2024
|
||||||
|
KernelVersion: 6.8.0
|
||||||
|
Contact: Adrian Larumbe <adrian.larumbe@collabora.com>
|
||||||
|
Description:
|
||||||
|
Get/set drm fdinfo's engine and cycles profiling status.
|
||||||
|
Valid values are:
|
||||||
|
0: Don't enable fdinfo job profiling sources.
|
||||||
|
1: Enable fdinfo job profiling sources, this enables both the GPU's
|
||||||
|
timestamp and cycle counter registers.
|
@ -38,3 +38,12 @@ the currently possible format options:
|
|||||||
|
|
||||||
Possible `drm-engine-` key names are: `fragment`, and `vertex-tiler`.
|
Possible `drm-engine-` key names are: `fragment`, and `vertex-tiler`.
|
||||||
`drm-curfreq-` values convey the current operating frequency for that engine.
|
`drm-curfreq-` values convey the current operating frequency for that engine.
|
||||||
|
|
||||||
|
Users must bear in mind that engine and cycle sampling are disabled by default,
|
||||||
|
because of power saving concerns. `fdinfo` users and benchmark applications which
|
||||||
|
query the fdinfo file must make sure to toggle the job profiling status of the
|
||||||
|
driver by writing into the appropriate sysfs node::
|
||||||
|
|
||||||
|
echo <N> > /sys/bus/platform/drivers/panfrost/[a-f0-9]*.gpu/profiling
|
||||||
|
|
||||||
|
Where `N` is either `0` or `1`, depending on the desired enablement status.
|
||||||
|
@ -12,6 +12,4 @@ panfrost-y := \
|
|||||||
panfrost_perfcnt.o \
|
panfrost_perfcnt.o \
|
||||||
panfrost_dump.o
|
panfrost_dump.o
|
||||||
|
|
||||||
panfrost-$(CONFIG_DEBUG_FS) += panfrost_debugfs.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_DRM_PANFROST) += panfrost.o
|
obj-$(CONFIG_DRM_PANFROST) += panfrost.o
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
|
||||||
/* Copyright 2023 Collabora ltd. */
|
|
||||||
/* Copyright 2023 Amazon.com, Inc. or its affiliates. */
|
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
|
||||||
#include <linux/platform_device.h>
|
|
||||||
#include <drm/drm_debugfs.h>
|
|
||||||
#include <drm/drm_file.h>
|
|
||||||
#include <drm/panfrost_drm.h>
|
|
||||||
|
|
||||||
#include "panfrost_device.h"
|
|
||||||
#include "panfrost_gpu.h"
|
|
||||||
#include "panfrost_debugfs.h"
|
|
||||||
|
|
||||||
void panfrost_debugfs_init(struct drm_minor *minor)
|
|
||||||
{
|
|
||||||
struct drm_device *dev = minor->dev;
|
|
||||||
struct panfrost_device *pfdev = platform_get_drvdata(to_platform_device(dev->dev));
|
|
||||||
|
|
||||||
debugfs_create_atomic_t("profile", 0600, minor->debugfs_root, &pfdev->profile_mode);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0 */
|
|
||||||
/*
|
|
||||||
* Copyright 2023 Collabora ltd.
|
|
||||||
* Copyright 2023 Amazon.com, Inc. or its affiliates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef PANFROST_DEBUGFS_H
|
|
||||||
#define PANFROST_DEBUGFS_H
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
void panfrost_debugfs_init(struct drm_minor *minor);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* PANFROST_DEBUGFS_H */
|
|
@ -130,7 +130,7 @@ struct panfrost_device {
|
|||||||
struct list_head scheduled_jobs;
|
struct list_head scheduled_jobs;
|
||||||
|
|
||||||
struct panfrost_perfcnt *perfcnt;
|
struct panfrost_perfcnt *perfcnt;
|
||||||
atomic_t profile_mode;
|
bool profile_mode;
|
||||||
|
|
||||||
struct mutex sched_lock;
|
struct mutex sched_lock;
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include "panfrost_job.h"
|
#include "panfrost_job.h"
|
||||||
#include "panfrost_gpu.h"
|
#include "panfrost_gpu.h"
|
||||||
#include "panfrost_perfcnt.h"
|
#include "panfrost_perfcnt.h"
|
||||||
#include "panfrost_debugfs.h"
|
|
||||||
|
|
||||||
static bool unstable_ioctls;
|
static bool unstable_ioctls;
|
||||||
module_param_unsafe(unstable_ioctls, bool, 0600);
|
module_param_unsafe(unstable_ioctls, bool, 0600);
|
||||||
@ -600,10 +599,6 @@ static const struct drm_driver panfrost_drm_driver = {
|
|||||||
|
|
||||||
.gem_create_object = panfrost_gem_create_object,
|
.gem_create_object = panfrost_gem_create_object,
|
||||||
.gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table,
|
.gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table,
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
.debugfs_init = panfrost_debugfs_init,
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int panfrost_probe(struct platform_device *pdev)
|
static int panfrost_probe(struct platform_device *pdev)
|
||||||
@ -692,6 +687,40 @@ static void panfrost_remove(struct platform_device *pdev)
|
|||||||
drm_dev_put(ddev);
|
drm_dev_put(ddev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t profiling_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct panfrost_device *pfdev = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return sysfs_emit(buf, "%d\n", pfdev->profile_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t profiling_store(struct device *dev,
|
||||||
|
struct device_attribute *attr,
|
||||||
|
const char *buf, size_t len)
|
||||||
|
{
|
||||||
|
struct panfrost_device *pfdev = dev_get_drvdata(dev);
|
||||||
|
bool value;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = kstrtobool(buf, &value);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
pfdev->profile_mode = value;
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RW(profiling);
|
||||||
|
|
||||||
|
static struct attribute *panfrost_attrs[] = {
|
||||||
|
&dev_attr_profiling.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
ATTRIBUTE_GROUPS(panfrost);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The OPP core wants the supply names to be NULL terminated, but we need the
|
* The OPP core wants the supply names to be NULL terminated, but we need the
|
||||||
* correct num_supplies value for regulator core. Hence, we NULL terminate here
|
* correct num_supplies value for regulator core. Hence, we NULL terminate here
|
||||||
@ -789,6 +818,7 @@ static struct platform_driver panfrost_driver = {
|
|||||||
.name = "panfrost",
|
.name = "panfrost",
|
||||||
.pm = pm_ptr(&panfrost_pm_ops),
|
.pm = pm_ptr(&panfrost_pm_ops),
|
||||||
.of_match_table = dt_match,
|
.of_match_table = dt_match,
|
||||||
|
.dev_groups = panfrost_groups,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
module_platform_driver(panfrost_driver);
|
module_platform_driver(panfrost_driver);
|
||||||
|
@ -243,7 +243,7 @@ static void panfrost_job_hw_submit(struct panfrost_job *job, int js)
|
|||||||
subslot = panfrost_enqueue_job(pfdev, js, job);
|
subslot = panfrost_enqueue_job(pfdev, js, job);
|
||||||
/* Don't queue the job if a reset is in progress */
|
/* Don't queue the job if a reset is in progress */
|
||||||
if (!atomic_read(&pfdev->reset.pending)) {
|
if (!atomic_read(&pfdev->reset.pending)) {
|
||||||
if (atomic_read(&pfdev->profile_mode)) {
|
if (pfdev->profile_mode) {
|
||||||
panfrost_cycle_counter_get(pfdev);
|
panfrost_cycle_counter_get(pfdev);
|
||||||
job->is_profiled = true;
|
job->is_profiled = true;
|
||||||
job->start_time = ktime_get();
|
job->start_time = ktime_get();
|
||||||
|
Loading…
Reference in New Issue
Block a user