mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
platform/x86/amd/pmf: Add util layer and userspace character device interface
Add a util layer to AMD PMF that exposes a minimal userspace interface via a character device for metrics monitoring and feature discovery. This creates /dev/amdpmf_interface with basic ioctl support to retrieve PMF metrics such as: * Power source and power slider position * Platform type, lid state, and user presence * Skin temperature and ambient light * BIOS input parameters (1-10) * Graphics workload metrics * CPU C-state residency (average and maximum) * Socket power consumption * Auto Mode: Automatic power profile switching based on system activity * Static Power Slider: User-selectable power profiles * Policy Builder (Smart PC): Action based policy management * Dynamic Power Slider AC: Adaptive power profiles when on AC power * Dynamic Power Slider DC: Adaptive power profiles when on battery The interface enables smoother integration with userspace tools such as AMD SystemDeck [1], which is widely used for monitoring and controlling power and thermal behavior on AMD platforms. These tools help designers keep major components within thermal limits to ensure proper operation and enhance overall system stability and reliability. The feature is gated behind the CONFIG_AMD_PMF_UTIL_SUPPORT Kconfig option, allowing it to be disabled if not needed. The implementation uses existing PMF infrastructure to populate data from the TA (Trusted Application) shared memory buffer. Link: https://docs.amd.com/v/u/en-US/68773_0.50 [1] Co-developed-by: Sanket Goswami <Sanket.Goswami@amd.com> Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> Link: https://patch.msgid.link/20260609081044.2416731-2-Shyam-sundar.S-k@amd.com Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
parent
4aefd66ef7
commit
98432eec31
|
|
@ -30,3 +30,13 @@ config AMD_PMF_DEBUG
|
|||
in the PMF config store.
|
||||
|
||||
Say Y here to enable more debug logs and Say N here if you are not sure.
|
||||
|
||||
config AMD_PMF_UTIL_SUPPORT
|
||||
bool "AMD PMF Util layer support"
|
||||
depends on AMD_PMF
|
||||
help
|
||||
Enabling this option provides a character device for userspace to capture
|
||||
PMF features (Smart PC Builder, Auto Mode, Static Power Slider, Dynamic
|
||||
Power Slider AC/DC) along with PMF metrics from the AMD PMF driver.
|
||||
|
||||
Say Y here to enable it and Say N here if you are not sure.
|
||||
|
|
|
|||
|
|
@ -8,3 +8,5 @@ obj-$(CONFIG_AMD_PMF) += amd-pmf.o
|
|||
amd-pmf-y := core.o acpi.o sps.o \
|
||||
auto-mode.o cnqf.o \
|
||||
tee-if.o spc.o
|
||||
# Build util.c only when AMD_PMF_UTIL_SUPPORT is enabled
|
||||
amd-pmf-$(CONFIG_AMD_PMF_UTIL_SUPPORT) += util.o
|
||||
|
|
|
|||
|
|
@ -634,6 +634,10 @@ static int amd_pmf_probe(struct platform_device *pdev)
|
|||
|
||||
pmf_device = dev->dev;
|
||||
|
||||
err = amd_pmf_cdev_register(dev);
|
||||
if (err)
|
||||
dev_warn(dev->dev, "failed to register util interface: %d\n", err);
|
||||
|
||||
dev_info(dev->dev, "registered PMF device successfully\n");
|
||||
|
||||
return 0;
|
||||
|
|
@ -643,6 +647,7 @@ static void amd_pmf_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct amd_pmf_dev *dev = platform_get_drvdata(pdev);
|
||||
|
||||
amd_pmf_cdev_unregister();
|
||||
amd_pmf_deinit_features(dev);
|
||||
if (is_apmf_func_supported(dev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
|
||||
amd_pmf_notify_sbios_heartbeat_event_v2(dev, ON_UNLOAD);
|
||||
|
|
|
|||
|
|
@ -928,4 +928,13 @@ int amd_pmf_tee_init(struct amd_pmf_dev *dev, const uuid_t *uuid);
|
|||
void amd_pmf_tee_deinit(struct amd_pmf_dev *dev);
|
||||
int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev);
|
||||
|
||||
/* Util Layer */
|
||||
#if IS_ENABLED(CONFIG_AMD_PMF_UTIL_SUPPORT)
|
||||
int amd_pmf_cdev_register(struct amd_pmf_dev *dev);
|
||||
void amd_pmf_cdev_unregister(void);
|
||||
#else
|
||||
static inline int amd_pmf_cdev_register(struct amd_pmf_dev *dev) { return 0; }
|
||||
static inline void amd_pmf_cdev_unregister(void) {}
|
||||
#endif
|
||||
|
||||
#endif /* PMF_H */
|
||||
|
|
|
|||
68
drivers/platform/x86/amd/pmf/util.c
Normal file
68
drivers/platform/x86/amd/pmf/util.c
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* AMD Platform Management Framework Util Layer
|
||||
*
|
||||
* Copyright (c) 2026, Advanced Micro Devices, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
|
||||
* Sanket Goswami <Sanket.Goswami@amd.com>
|
||||
*/
|
||||
|
||||
#include <linux/amd-pmf.h>
|
||||
#include <linux/miscdevice.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "pmf.h"
|
||||
|
||||
static struct amd_pmf_dev *pmf_dev_handle;
|
||||
static DEFINE_MUTEX(pmf_util_lock);
|
||||
|
||||
static long amd_pmf_set_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static int amd_pmf_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
guard(mutex)(&pmf_util_lock);
|
||||
if (!pmf_dev_handle)
|
||||
return -ENODEV;
|
||||
|
||||
filp->private_data = pmf_dev_handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations pmf_if_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = amd_pmf_open,
|
||||
.unlocked_ioctl = amd_pmf_set_ioctl,
|
||||
};
|
||||
|
||||
static struct miscdevice amd_pmf_util_if = {
|
||||
.minor = MISC_DYNAMIC_MINOR,
|
||||
.name = "amdpmf_interface",
|
||||
.fops = &pmf_if_ops,
|
||||
};
|
||||
|
||||
int amd_pmf_cdev_register(struct amd_pmf_dev *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&pmf_util_lock);
|
||||
pmf_dev_handle = dev;
|
||||
ret = misc_register(&amd_pmf_util_if);
|
||||
if (ret)
|
||||
pmf_dev_handle = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void amd_pmf_cdev_unregister(void)
|
||||
{
|
||||
guard(mutex)(&pmf_util_lock);
|
||||
if (pmf_dev_handle)
|
||||
misc_deregister(&amd_pmf_util_if);
|
||||
pmf_dev_handle = NULL;
|
||||
}
|
||||
71
include/uapi/linux/amd-pmf.h
Normal file
71
include/uapi/linux/amd-pmf.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */
|
||||
/*
|
||||
* AMD Platform Management Framework (PMF) UAPI Header
|
||||
*
|
||||
* Copyright (c) 2026, Advanced Micro Devices, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This file defines the user-space API for interacting with the AMD PMF
|
||||
* driver. It provides ioctl interfaces to query platform-specific metrics
|
||||
* such as power source, slider position, platform type, laptop placement,
|
||||
* and various BIOS input/output parameters.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_LINUX_AMD_PMF_H
|
||||
#define _UAPI_LINUX_AMD_PMF_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* AMD_PMF_IOC_MAGIC - Magic number for AMD PMF ioctl commands
|
||||
*
|
||||
* This magic number uniquely identifies AMD PMF ioctl operations.
|
||||
*/
|
||||
#define AMD_PMF_IOC_MAGIC 'p'
|
||||
|
||||
/**
|
||||
* IOCTL_AMD_PMF_POPULATE_DATA - ioctl command to retrieve PMF metrics data
|
||||
*
|
||||
* This ioctl command is used to populate the amd_pmf_info structure
|
||||
* with the requested PMF metrics information.
|
||||
*/
|
||||
#define IOCTL_AMD_PMF_POPULATE_DATA _IOWR(AMD_PMF_IOC_MAGIC, 0x00, __u64)
|
||||
|
||||
#define AMD_PMF_BIOS_PARAMS_MAX 10
|
||||
|
||||
/* AMD PMF feature flags - bitmask indicating supported features */
|
||||
#define AMD_PMF_FEAT_AUTO_MODE BIT(0)
|
||||
#define AMD_PMF_FEAT_STATIC_POWER_SLIDER BIT(1)
|
||||
#define AMD_PMF_FEAT_POLICY_BUILDER BIT(2)
|
||||
#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_AC BIT(3)
|
||||
#define AMD_PMF_FEAT_DYNAMIC_POWER_SLIDER_DC BIT(4)
|
||||
|
||||
struct amd_pmf_info {
|
||||
__u64 size;
|
||||
|
||||
/* Feature info */
|
||||
__u32 features_supported;
|
||||
|
||||
/* Power and state info */
|
||||
__u32 platform_type;
|
||||
__u32 power_source;
|
||||
__u32 laptop_placement;
|
||||
__u32 lid_state;
|
||||
__u32 user_presence;
|
||||
__u32 slider_position;
|
||||
|
||||
/* Thermal and power metrics */
|
||||
__s32 skin_temp;
|
||||
__u32 gfx_busy;
|
||||
__s32 ambient_light;
|
||||
__u32 avg_c0_residency;
|
||||
__u32 max_c0_residency;
|
||||
__u32 socket_power;
|
||||
|
||||
/* BIOS parameters */
|
||||
__u32 bios_input[AMD_PMF_BIOS_PARAMS_MAX];
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_AMD_PMF_H */
|
||||
Loading…
Reference in New Issue
Block a user