+ Selftest people.

On Sun, 1 Mar 2026, Shyam Sundar S K wrote:

> This tool leverages amd-pmf ioctls exposed via the util layer, allowing
> validation of its newly integrated util layer and /dev/amdpmf_interface.
> It includes a user-space test application, test_pmf, designed to interact
> with the PMF driver and retrieve relevant metrics for the testing and
> analysis.
> 
> It provides definitions for test metrics, feature IDs, and device states,
> and includes tests for various AMD PMF metrics such as power source, skin
> temperature, battery state, and custom BIOS inputs/outputs. It also
> enables the testing of PMF metrics data and feature support reporting.
> 
> Co-developed-by: Sanket Goswami <[email protected]>
> Signed-off-by: Sanket Goswami <[email protected]>
> Signed-off-by: Shyam Sundar S K <[email protected]>
> ---
>  tools/testing/selftests/Makefile              |   1 +
>  .../drivers/platform/x86/amd/pmf/Makefile     |   8 +
>  .../drivers/platform/x86/amd/pmf/test_pmf.c   | 243 ++++++++++++++++++
>  3 files changed, 252 insertions(+)
>  create mode 100644 
> tools/testing/selftests/drivers/platform/x86/amd/pmf/Makefile
>  create mode 100644 
> tools/testing/selftests/drivers/platform/x86/amd/pmf/test_pmf.c

Please Cc also selftest people in the next version submission! Maube you 
should also check why your patch sending process did not capture those 
receipient for you.

To me it looks this "tool" doesn't really perform a selftest the way I've 
understood "selftests" work. That is, it doesn't have notion of Pass/Fail 
at all AFAICT. I'm not sure if there are other selftests like this but 
hopefully the selftest people know.

> diff --git a/tools/testing/selftests/Makefile 
> b/tools/testing/selftests/Makefile
> index 450f13ba4cca..d850fb09eeb9 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -26,6 +26,7 @@ TARGETS += drivers/net/netconsole
>  TARGETS += drivers/net/team
>  TARGETS += drivers/net/virtio_net
>  TARGETS += drivers/platform/x86/intel/ifs
> +TARGETS += drivers/platform/x86/amd/pmf
>  TARGETS += dt
>  TARGETS += efivarfs
>  TARGETS += exec
> diff --git a/tools/testing/selftests/drivers/platform/x86/amd/pmf/Makefile 
> b/tools/testing/selftests/drivers/platform/x86/amd/pmf/Makefile
> new file mode 100644
> index 000000000000..876424941e83
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/platform/x86/amd/pmf/Makefile
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: GPL-2.0-or-later
> +CFLAGS += $(KHDR_INCLUDES)
> +
> +TEST_GEN_PROGS := test_pmf
> +
> +top_srcdir ?=../../../../..
> +
> +include ../../../../../lib.mk
> diff --git a/tools/testing/selftests/drivers/platform/x86/amd/pmf/test_pmf.c 
> b/tools/testing/selftests/drivers/platform/x86/amd/pmf/test_pmf.c
> new file mode 100644
> index 000000000000..a040ef01ba90
> --- /dev/null
> +++ b/tools/testing/selftests/drivers/platform/x86/amd/pmf/test_pmf.c
> @@ -0,0 +1,243 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * AMD Platform Management Framework Test Tool
> + *
> + * Copyright (c) 2026, Advanced Micro Devices, Inc.
> + * All Rights Reserved.
> + *
> + * Authors: Shyam Sundar S K <[email protected]>
> + *       Sanket Goswami <[email protected]>
> + */
> +
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <inttypes.h>
> +#include <stdbool.h>
> +#include <stdint.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +#include <unistd.h>
> +#include <linux/amd-pmf.h>
> +
> +#include "../../../../../kselftest.h"
> +
> +#define DEVICE_NODE          "/dev/amdpmf_interface"
> +
> +static int pmf_open_device(void)
> +{
> +     int fd;
> +
> +     fd = open(DEVICE_NODE, O_RDONLY);
> +     if (fd < 0)
> +             fprintf(stderr, "opening PMF Device Node failed: %s\n", 
> strerror(errno));
> +
> +     return fd;
> +}
> +
> +/* Helper to run IOCTL_PMF_POPULATE_DATA for one control code and return 0 
> on success. */

Reflow this comment to 80 chars.

> +static int pmf_get_fd(int fd, enum pmf_ioctl_id code, struct 
> amd_pmf_ioctl_info *out)
> +{
> +     struct amd_pmf_ioctl_info info = {0};

= {}; should be enough to initialize to default values.

> +     int ret;
> +
> +     if (!out)
> +             return -EINVAL;
> +
> +     info.control_code = code;
> +
> +     ret = ioctl(fd, IOCTL_PMF_POPULATE_DATA, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     *out = info;
> +     return 0;
> +}
> +
> +static int pmf_get_data(enum pmf_ioctl_id code, struct amd_pmf_ioctl_info 
> *out)
> +{
> +     int fd, ret;
> +
> +     fd = pmf_open_device();
> +     if (fd < 0)
> +             return fd;
> +
> +     ret = pmf_get_fd(fd, code, out);
> +
> +     close(fd);
> +     return ret;
> +}
> +
> +static int pmf_get_feature_status(unsigned int code)
> +{
> +     struct amd_pmf_ioctl_info info = {0};
> +     int ret;
> +
> +     ret = pmf_get_data(code, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     switch (code) {
> +     case IOCTL_FEATURE_AUTO_MODE:
> +             printf("Auto Mode: %-24s\n", info.feature_supported ? "Yes" : 
> "No");
> +             break;
> +     case IOCTL_FEATURE_STATIC_POWER_SLIDER:
> +             printf("Static Power Slider: %-24s\n", info.feature_supported ? 
> "Yes" : "No");
> +             break;
> +     case IOCTL_FEATURE_POLICY_BUILDER:
> +             printf("Policy Builder: %s\n", info.feature_supported ? "Yes" : 
> "No");
> +             break;
> +     case IOCTL_FEATURE_DYNAMIC_POWER_SLIDER_AC:
> +             printf("Dynamic Power Slider AC: %s\n", info.feature_supported 
> ? "Yes" : "No");
> +             break;
> +     case IOCTL_FEATURE_DYNAMIC_POWER_SLIDER_DC:
> +             printf("Dynamic Power Slider DC: %s\n", info.feature_supported 
> ? "Yes" : "No");
> +             break;
> +     default:
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +static int pmf_get_device_state(unsigned int code)
> +{
> +     struct amd_pmf_ioctl_info info = {0};
> +     int ret;
> +
> +     ret = pmf_get_data(code, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     switch (code) {
> +     case IOCTL_PLATFORM_TYPE:
> +             printf("Platform Type: %s\n", platform_type_as_str(info.val));
> +             break;
> +     case IOCTL_LAPTOP_PLACEMENT:
> +             printf("Laptop placement: %s\n", 
> laptop_placement_as_str(info.val));
> +             break;
> +     case IOCTL_LID_STATE:
> +             printf("Lid State: %s\n", info.val ? "Close" : "Open");
> +             break;
> +     case IOCTL_USER_PRESENCE:
> +             printf("User Presence: %s\n", info.val ? "Present" : "Away");
> +             break;
> +     default:
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +static int pmf_get_custom_bios_input(unsigned int code)
> +{
> +     struct amd_pmf_ioctl_info info = {0};
> +     int idx, ret;
> +
> +     ret = pmf_get_data(code, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     switch (code) {
> +     case IOCTL_BIOS_INPUT_1 ... IOCTL_BIOS_INPUT_10:
> +             idx = amd_pmf_get_bios_idx(code);
> +             printf("Custom BIOS input%u: %lu\n", idx + 1, 
> (int64_t)info.val);

%lu is for printing unsigned long, not int64_t.

> +             break;
> +     default:
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +static int pmf_get_bios_output(unsigned int code)
> +{
> +     struct amd_pmf_ioctl_info info = {0};
> +     int idx, ret;
> +
> +     ret = pmf_get_data(code, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     switch (code) {
> +     case IOCTL_BIOS_OUTPUT_1 ... IOCTL_BIOS_OUTPUT_10:
> +             idx = amd_pmf_get_bios_idx(code);
> +             printf("BIOS output%u: %lu\n", idx + 1, (int64_t)info.val);
> +             break;
> +     default:
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +static int pmf_get_misc_info(unsigned int code)
> +{
> +     struct amd_pmf_ioctl_info info = {0};
> +     int ret;
> +
> +     ret = pmf_get_data(code, &info);
> +     if (ret < 0)
> +             return ret;
> +
> +     switch (code) {
> +     case IOCTL_POWER_SLIDER_POSITION:
> +             printf("Slider Position: %s\n", ta_slider_as_str(info.val));
> +             break;
> +     case IOCTL_SKIN_TEMP:
> +             printf("Skin Temperature: %lu\n", (int64_t)info.val);
> +             break;
> +     case IOCTL_GFX_WORKLOAD:
> +             printf("GFX Busy: %lu\n", (int64_t)info.val);
> +             break;
> +     case IOCTL_AMBIENT_LIGHT:
> +             printf("Ambient Light: %ld\n", (int64_t)info.val);
> +             break;
> +     case IOCTL_AVG_C0_RES:
> +             printf("Avg C0 Residency: %lu\n", (int64_t)info.val);
> +             break;
> +     case IOCTL_MAX_C0_RES:
> +             printf("Max C0 Residency: %lu\n", (int64_t)info.val);
> +             break;
> +     case IOCTL_SOCKET_POWER:
> +             printf("Socket Power: %lu\n", (int64_t)info.val);

Please think the printf formatting strings and types through.

> +             break;
> +     default:
> +             return -1;
> +     }
> +
> +     return 0;
> +}
> +
> +int main(void)
> +{
> +     unsigned int idx;
> +
> +     printf("Feature Name          Supported\n");
> +     printf("---------------------------------\n");
> +     for (idx = IOCTL_FEATURE_AUTO_MODE; idx <= 
> IOCTL_FEATURE_DYNAMIC_POWER_SLIDER_DC; idx++)
> +             pmf_get_feature_status(idx);
> +
> +     printf("\nDevice State\n---------------\n");
> +     for (idx = IOCTL_PLATFORM_TYPE; idx <= IOCTL_USER_PRESENCE; idx++)
> +             pmf_get_device_state(idx);
> +
> +     printf("\nCustom BIOS Inputs\n-------------------\n");
> +     for (idx = IOCTL_BIOS_INPUT_1; idx <= IOCTL_BIOS_INPUT_10; idx++)
> +             pmf_get_custom_bios_input(idx);
> +
> +     printf("\nBIOS Outputs\n--------------\n");
> +     for (idx = IOCTL_BIOS_OUTPUT_1; idx <= IOCTL_BIOS_OUTPUT_10; idx++)
> +             pmf_get_bios_output(idx);
> +
> +     printf("\nMisc\n------\n");
> +     pmf_get_misc_info(IOCTL_SKIN_TEMP);
> +     pmf_get_misc_info(IOCTL_GFX_WORKLOAD);
> +     pmf_get_misc_info(IOCTL_AMBIENT_LIGHT);
> +     pmf_get_misc_info(IOCTL_AVG_C0_RES);
> +     pmf_get_misc_info(IOCTL_MAX_C0_RES);
> +     pmf_get_misc_info(IOCTL_SOCKET_POWER);
> +     pmf_get_misc_info(IOCTL_POWER_SLIDER_POSITION);
> +
> +     return 0;
> +}
> 

-- 
 i.


Reply via email to