From patchwork Tue Oct 8 17:43:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tummala, Sivaprasad" X-Patchwork-Id: 145483 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 1E42D45AE3; Tue, 8 Oct 2024 19:43:38 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0AEA440BA5; Tue, 8 Oct 2024 19:43:38 +0200 (CEST) Received: from NAM02-BN1-obe.outbound.protection.outlook.com (mail-bn1nam02on2056.outbound.protection.outlook.com [40.107.212.56]) by mails.dpdk.org (Postfix) with ESMTP id BB0EA4025C for ; Tue, 8 Oct 2024 19:43:36 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=CyI8BXr/AiLaCa1r2L5FRBUKZu+qIdGyxd8UZut4LPYJcVyIb06dYLt4EpkNEUTp59gpA0KkAli8GPC8IVYBaGyWsc262Zh39DHUda1wpWH1bqiBpEICZn7d2yVHXNNW3YovT10RqcJHQYy0yJaOSwgV/tjEdSaEasmifHQCWudG1U36Gy/6oewSjkjgoFrSxRGSW94qnLym9yi58AXQwkvgnhk7Kx1Zqo6qOllWsyfsSy5TkG0f6fXV8HOZnd1qfdBz8iCd4+YjFpEYwBN8MiZZWany6SlQvJq+rcFRSIArgokbBI2FZ2PT0S8nTFSFAigh7iAXTNuYk3Z9kYPsfQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=CBfxMi7FrvweKWz2d49DUBr4QyT5cVXueSB5FnG5+Z8=; b=WC2ESheTm2Xfhmlt1fKgo051G2vmP9Mb6YS05ebw8dmoLUAgty3vZdfSOludkDnMWYvD06NfQuTSEKVJmV7n14MSwVscAmOl71RPKyxZ9g0ciIpP46vJlzSWsTc18Au/D27LrBOz1//vw/Ektd01RTYnFl9AnxjoIs/HTriiz9okHbI88nJJ+d1U98PUnNJYpwvSQ9xNnaDBW1Wqp5pZJq34HwPeCK/uVIWi+zk+mA4gb1kqJ80RU77WzTHaochaSADvV6jf94ivSiwYthf1d1jCHv8DFenLoZnoHQH6QSVwDUHRSCFgYSu9yjt21D/yMDFBjKjE32VNac18zzLEPQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 165.204.84.17) smtp.rcpttodomain=intel.com smtp.mailfrom=amd.com; dmarc=pass (p=quarantine sp=quarantine pct=100) action=none header.from=amd.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amd.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=CBfxMi7FrvweKWz2d49DUBr4QyT5cVXueSB5FnG5+Z8=; b=zfFRtAi8kILxKiKIJh8YzMovZTFE6Qgi+VJ+kj307L+FVH4VWoZ4Kn/i2RIPd8KIzhCplL+V/zM1OP4jWcJIhduhYJJiwigodnQmniRJUDcL7u5IbYyJE9wH1rmga8P/626KWHdW1S5HkY5BTbs4BLB/BUWAh9JUQG6ghkpc3wc= Received: from BN0PR04CA0055.namprd04.prod.outlook.com (2603:10b6:408:e8::30) by CH2PR12MB4231.namprd12.prod.outlook.com (2603:10b6:610:7d::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8026.23; Tue, 8 Oct 2024 17:43:31 +0000 Received: from BN3PEPF0000B372.namprd21.prod.outlook.com (2603:10b6:408:e8:cafe::ed) by BN0PR04CA0055.outlook.office365.com (2603:10b6:408:e8::30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8026.24 via Frontend Transport; Tue, 8 Oct 2024 17:43:30 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=amd.com; Received-SPF: Pass (protection.outlook.com: domain of amd.com designates 165.204.84.17 as permitted sender) receiver=protection.outlook.com; client-ip=165.204.84.17; helo=SATLEXMB04.amd.com; pr=C Received: from SATLEXMB04.amd.com (165.204.84.17) by BN3PEPF0000B372.mail.protection.outlook.com (10.167.243.169) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8069.0 via Frontend Transport; Tue, 8 Oct 2024 17:43:29 +0000 Received: from jfw9ny3-os.amd.com (10.180.168.240) by SATLEXMB04.amd.com (10.181.40.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Tue, 8 Oct 2024 12:43:25 -0500 From: Sivaprasad Tummala To: , , , , , , , CC: Subject: [PATCH v3 1/5] power: refactor core power management library Date: Tue, 8 Oct 2024 17:43:04 +0000 Message-ID: <20241008174309.1133051-2-sivaprasad.tummala@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241008174309.1133051-1-sivaprasad.tummala@amd.com> References: <20241008172719.902619-1-sivaprasad.tummala@amd.com> <20241008174309.1133051-1-sivaprasad.tummala@amd.com> MIME-Version: 1.0 X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB04.amd.com (10.181.40.145) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN3PEPF0000B372:EE_|CH2PR12MB4231:EE_ X-MS-Office365-Filtering-Correlation-Id: 440a8ee9-488f-487b-802f-08dce7c0b888 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|376014|82310400026|1800799024|36860700013; X-Microsoft-Antispam-Message-Info: RX5Y9px6qYegRkEnoEePA2C4CfThM8R95HE5+hm9vT87zkSiNQdHMAXRLn2FYyb+3MsVpU7GEVMV1+gUdxf/rdS97VD+QXnUaUpCwBIg3Pd/K3ecFI589L/ON5gwAjVEMjLnCAS5UG0bMco5UYPqRRiqWMwNdNR/aFUefNfUPpfPf7+eb/9zSSasmNib0FfOofrVu2/d8ZT2bOxKpYQeL+T8/f8Shk/z/IioQ7UL5/JZXU5w05jZ6rdTBtxzwJOHu7WWL9RqYJMFiQ0Iqc6RPBbHQqFsCkVxQSg4PeDL3WJynag62oY1AujafrdhdHFgjqqPABi32wrNGvUvxhwWGSFmaSLbms5ehiTo5H+tt+XZM1UIEVo/87IGZSYeBZNBXgYSECUXvsUmooB0wVHIrKsvhbom4zOH+VYDgelJx3IdwsEpKFkweb2cP4Yek4ZELHu0uwSpt0/Nk0IGLNltgBRuGvLMiHt39qD4Q4N4pWz4MxtTvWlsYMr2iWjdrW86EPjffIRwQ4Kwqu8HJRD9/PBbfvqZf5vqSPTxZQcvjmE8aODOH1ZwYJDp7yuudg2c6HF57uszPZ7hWQ6NETgLGw/zqYwLwAxjxb1tbI8GxuOC/tzJugMTL0TyP0Gj/VqrQgalPLpg4KjMAORrfeqW7VS4jsfKBlD4n+vsAbmMzQPHXBEGFqgANhi9xE4zfsylA3mxK3n2N5x4gnxMf0JH1G4LnO6NNMM7Hp8CxbOAK4dQgQbqe+Xjg0uLasLmSYjTMkVBuxBaiL/97YLLYzPyjoPEQCStPUlIKKsPQyIKq9Ih3RoO2uWsMkofNjLik51cVm/g0bYZTTXTj8jZD9OeubU1IfBmvSzaAIAVohg2wjOWfwdoD8eAPeIa+eERlt7836YUfEz5ByD+U8Ph9in4ObQZ0AP6RfuQN6vXc3wpR5deROHx6zE0CFxG9If14vs4A7IQDdZmvp2bBxlI63V+nMUIN1JQNDC3JLHDCW9CV42YeKnN7WSvozklL9vwYINam1oUl2ugEEUomLr7ZJi5UCuxNyy/SzT85Qjbt77ZOgQ/4k//zrXr1+tTRCOvakoPKflR4AlIkKgEqDPdBJRaJW1+c1iUxr6Y8KmiAzaY9EU82zSc8PZk/2SxhFBAYx08Cxc507Za5Wf83HiL3vGe+hzPfQuSgka/TgrCIMpMkkT1NYovvYbxS612d6ydHlQaKM7LPmMJkqIAIXw3M9fUSAU6dqNpCM4z1Yv/wtULG57OF3qugEm7dLKRJJymreknl9UT/jIQLZOn0IsCtgu7Xiazn5i4MsKI4qxVRNG7lM3SC+tLQYBF0wwFftIGPNoOAnhfNodDrCvcjWt/auQweekLhStsJ2ce/H2pxSCGz05y002cErfsIQIQI7/ILPsU X-Forefront-Antispam-Report: CIP:165.204.84.17; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:SATLEXMB04.amd.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(376014)(82310400026)(1800799024)(36860700013); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Oct 2024 17:43:29.4833 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 440a8ee9-488f-487b-802f-08dce7c0b888 X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXMB04.amd.com] X-MS-Exchange-CrossTenant-AuthSource: BN3PEPF0000B372.namprd21.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CH2PR12MB4231 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This patch introduces a comprehensive refactor to the core power management library. The primary focus is on improving modularity and organization by relocating specific driver implementations from the 'lib/power' directory to dedicated directories within 'drivers/power/core/*'. The adjustment of meson.build files enables the selective activation of individual drivers. These changes contribute to a significant enhancement in code organization, providing a clearer structure for driver implementations. The refactor aims to improve overall code clarity and boost maintainability. Additionally, it establishes a foundation for future development, allowing for more focused work on individual drivers and seamless integration of forthcoming enhancements. v3: - renamed rte_power_core_ops.h as rte_power_cpufreq_api.h - re-worked on auto detection logic v2: - added NULL check for global_core_ops in rte_power_get_core_ops Signed-off-by: Sivaprasad Tummala --- drivers/meson.build | 1 + .../power/acpi/acpi_cpufreq.c | 22 +- .../power/acpi/acpi_cpufreq.h | 6 +- drivers/power/acpi/meson.build | 10 + .../power/amd_pstate/amd_pstate_cpufreq.c | 24 +- .../power/amd_pstate/amd_pstate_cpufreq.h | 8 +- drivers/power/amd_pstate/meson.build | 10 + .../power/cppc/cppc_cpufreq.c | 22 +- .../power/cppc/cppc_cpufreq.h | 8 +- drivers/power/cppc/meson.build | 10 + .../power/kvm_vm}/guest_channel.c | 0 .../power/kvm_vm}/guest_channel.h | 0 .../power/kvm_vm/kvm_vm.c | 22 +- .../power/kvm_vm/kvm_vm.h | 6 +- drivers/power/kvm_vm/meson.build | 16 + drivers/power/meson.build | 12 + drivers/power/pstate/meson.build | 10 + .../power/pstate/pstate_cpufreq.c | 22 +- .../power/pstate/pstate_cpufreq.h | 6 +- lib/power/meson.build | 7 +- lib/power/power_common.c | 2 +- lib/power/power_common.h | 16 +- lib/power/rte_power.c | 286 ++++++------------ lib/power/rte_power.h | 139 ++++++--- lib/power/rte_power_cpufreq_api.h | 208 +++++++++++++ lib/power/version.map | 14 + 26 files changed, 618 insertions(+), 269 deletions(-) rename lib/power/power_acpi_cpufreq.c => drivers/power/acpi/acpi_cpufreq.c (95%) rename lib/power/power_acpi_cpufreq.h => drivers/power/acpi/acpi_cpufreq.h (98%) create mode 100644 drivers/power/acpi/meson.build rename lib/power/power_amd_pstate_cpufreq.c => drivers/power/amd_pstate/amd_pstate_cpufreq.c (95%) rename lib/power/power_amd_pstate_cpufreq.h => drivers/power/amd_pstate/amd_pstate_cpufreq.h (97%) create mode 100644 drivers/power/amd_pstate/meson.build rename lib/power/power_cppc_cpufreq.c => drivers/power/cppc/cppc_cpufreq.c (95%) rename lib/power/power_cppc_cpufreq.h => drivers/power/cppc/cppc_cpufreq.h (97%) create mode 100644 drivers/power/cppc/meson.build rename {lib/power => drivers/power/kvm_vm}/guest_channel.c (100%) rename {lib/power => drivers/power/kvm_vm}/guest_channel.h (100%) rename lib/power/power_kvm_vm.c => drivers/power/kvm_vm/kvm_vm.c (82%) rename lib/power/power_kvm_vm.h => drivers/power/kvm_vm/kvm_vm.h (98%) create mode 100644 drivers/power/kvm_vm/meson.build create mode 100644 drivers/power/meson.build create mode 100644 drivers/power/pstate/meson.build rename lib/power/power_pstate_cpufreq.c => drivers/power/pstate/pstate_cpufreq.c (96%) rename lib/power/power_pstate_cpufreq.h => drivers/power/pstate/pstate_cpufreq.h (98%) create mode 100644 lib/power/rte_power_cpufreq_api.h diff --git a/drivers/meson.build b/drivers/meson.build index 66931d4241..9d77e0deab 100644 --- a/drivers/meson.build +++ b/drivers/meson.build @@ -29,6 +29,7 @@ subdirs = [ 'event', # depends on common, bus, mempool and net. 'baseband', # depends on common and bus. 'gpu', # depends on common and bus. + 'power', # depends on common (in future). ] if meson.is_cross_build() diff --git a/lib/power/power_acpi_cpufreq.c b/drivers/power/acpi/acpi_cpufreq.c similarity index 95% rename from lib/power/power_acpi_cpufreq.c rename to drivers/power/acpi/acpi_cpufreq.c index 81996e1c13..8637c69703 100644 --- a/lib/power/power_acpi_cpufreq.c +++ b/drivers/power/acpi/acpi_cpufreq.c @@ -10,7 +10,7 @@ #include #include -#include "power_acpi_cpufreq.h" +#include "acpi_cpufreq.h" #include "power_common.h" #define STR_SIZE 1024 @@ -577,3 +577,23 @@ int power_acpi_get_capabilities(unsigned int lcore_id, return 0; } + +static struct rte_power_core_ops acpi_ops = { + .name = "acpi", + .init = power_acpi_cpufreq_init, + .exit = power_acpi_cpufreq_exit, + .check_env_support = power_acpi_cpufreq_check_supported, + .get_avail_freqs = power_acpi_cpufreq_freqs, + .get_freq = power_acpi_cpufreq_get_freq, + .set_freq = power_acpi_cpufreq_set_freq, + .freq_down = power_acpi_cpufreq_freq_down, + .freq_up = power_acpi_cpufreq_freq_up, + .freq_max = power_acpi_cpufreq_freq_max, + .freq_min = power_acpi_cpufreq_freq_min, + .turbo_status = power_acpi_turbo_status, + .enable_turbo = power_acpi_enable_turbo, + .disable_turbo = power_acpi_disable_turbo, + .get_caps = power_acpi_get_capabilities +}; + +RTE_POWER_REGISTER_OPS(acpi_ops); diff --git a/lib/power/power_acpi_cpufreq.h b/drivers/power/acpi/acpi_cpufreq.h similarity index 98% rename from lib/power/power_acpi_cpufreq.h rename to drivers/power/acpi/acpi_cpufreq.h index 682fd9278c..c685008fb5 100644 --- a/lib/power/power_acpi_cpufreq.h +++ b/drivers/power/acpi/acpi_cpufreq.h @@ -2,15 +2,15 @@ * Copyright(c) 2010-2014 Intel Corporation */ -#ifndef _POWER_ACPI_CPUFREQ_H -#define _POWER_ACPI_CPUFREQ_H +#ifndef _ACPI_CPUFREQ_H +#define _ACPI_CPUFREQ_H /** * @file * RTE Power Management via userspace ACPI cpufreq */ -#include "rte_power.h" +#include "rte_power_cpufreq_api.h" /** * Check if ACPI power management is supported. diff --git a/drivers/power/acpi/meson.build b/drivers/power/acpi/meson.build new file mode 100644 index 0000000000..f5afc893ce --- /dev/null +++ b/drivers/power/acpi/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +if not is_linux + build = false + reason = 'only supported on Linux' +endif +sources = files('acpi_cpufreq.c') + +deps += ['power'] diff --git a/lib/power/power_amd_pstate_cpufreq.c b/drivers/power/amd_pstate/amd_pstate_cpufreq.c similarity index 95% rename from lib/power/power_amd_pstate_cpufreq.c rename to drivers/power/amd_pstate/amd_pstate_cpufreq.c index 090a0d96cb..f571f4184a 100644 --- a/lib/power/power_amd_pstate_cpufreq.c +++ b/drivers/power/amd_pstate/amd_pstate_cpufreq.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2021 Intel Corporation * Copyright(c) 2021 Arm Limited - * Copyright(c) 2023 Amd Limited + * Copyright(c) 2024 Advanced Micro Devices, Inc. */ #include @@ -9,7 +9,7 @@ #include #include -#include "power_amd_pstate_cpufreq.h" +#include "amd_pstate_cpufreq.h" #include "power_common.h" /* macros used for rounding frequency to nearest 1000 */ @@ -700,3 +700,23 @@ power_amd_pstate_get_capabilities(unsigned int lcore_id, return 0; } + +static struct rte_power_core_ops amd_pstate_ops = { + .name = "amd-pstate", + .init = power_amd_pstate_cpufreq_init, + .exit = power_amd_pstate_cpufreq_exit, + .check_env_support = power_amd_pstate_cpufreq_check_supported, + .get_avail_freqs = power_amd_pstate_cpufreq_freqs, + .get_freq = power_amd_pstate_cpufreq_get_freq, + .set_freq = power_amd_pstate_cpufreq_set_freq, + .freq_down = power_amd_pstate_cpufreq_freq_down, + .freq_up = power_amd_pstate_cpufreq_freq_up, + .freq_max = power_amd_pstate_cpufreq_freq_max, + .freq_min = power_amd_pstate_cpufreq_freq_min, + .turbo_status = power_amd_pstate_turbo_status, + .enable_turbo = power_amd_pstate_enable_turbo, + .disable_turbo = power_amd_pstate_disable_turbo, + .get_caps = power_amd_pstate_get_capabilities +}; + +RTE_POWER_REGISTER_OPS(amd_pstate_ops); diff --git a/lib/power/power_amd_pstate_cpufreq.h b/drivers/power/amd_pstate/amd_pstate_cpufreq.h similarity index 97% rename from lib/power/power_amd_pstate_cpufreq.h rename to drivers/power/amd_pstate/amd_pstate_cpufreq.h index b02f9f98e4..17bd8e2eaf 100644 --- a/lib/power/power_amd_pstate_cpufreq.h +++ b/drivers/power/amd_pstate/amd_pstate_cpufreq.h @@ -1,18 +1,18 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2021 Intel Corporation * Copyright(c) 2021 Arm Limited - * Copyright(c) 2023 Amd Limited + * Copyright(c) 2024 Advanced Micro Devices, Inc. */ -#ifndef _POWER_AMD_PSTATE_CPUFREQ_H -#define _POWER_AMD_PSTATE_CPUFREQ_H +#ifndef _AMD_PSTATE_CPUFREQ_H +#define _AMD_PSTATE_CPUFREQ_H /** * @file * RTE Power Management via userspace AMD pstate cpufreq */ -#include "rte_power.h" +#include "rte_power_cpufreq_api.h" /** * Check if amd p-state power management is supported. diff --git a/drivers/power/amd_pstate/meson.build b/drivers/power/amd_pstate/meson.build new file mode 100644 index 0000000000..acaf20b388 --- /dev/null +++ b/drivers/power/amd_pstate/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +if not is_linux + build = false + reason = 'only supported on Linux' +endif +sources = files('amd_pstate_cpufreq.c') + +deps += ['power'] diff --git a/lib/power/power_cppc_cpufreq.c b/drivers/power/cppc/cppc_cpufreq.c similarity index 95% rename from lib/power/power_cppc_cpufreq.c rename to drivers/power/cppc/cppc_cpufreq.c index 32aaacb948..775b8f4434 100644 --- a/lib/power/power_cppc_cpufreq.c +++ b/drivers/power/cppc/cppc_cpufreq.c @@ -8,7 +8,7 @@ #include #include -#include "power_cppc_cpufreq.h" +#include "cppc_cpufreq.h" #include "power_common.h" /* macros used for rounding frequency to nearest 100000 */ @@ -685,3 +685,23 @@ power_cppc_get_capabilities(unsigned int lcore_id, return 0; } + +static struct rte_power_core_ops cppc_ops = { + .name = "cppc", + .init = power_cppc_cpufreq_init, + .exit = power_cppc_cpufreq_exit, + .check_env_support = power_cppc_cpufreq_check_supported, + .get_avail_freqs = power_cppc_cpufreq_freqs, + .get_freq = power_cppc_cpufreq_get_freq, + .set_freq = power_cppc_cpufreq_set_freq, + .freq_down = power_cppc_cpufreq_freq_down, + .freq_up = power_cppc_cpufreq_freq_up, + .freq_max = power_cppc_cpufreq_freq_max, + .freq_min = power_cppc_cpufreq_freq_min, + .turbo_status = power_cppc_turbo_status, + .enable_turbo = power_cppc_enable_turbo, + .disable_turbo = power_cppc_disable_turbo, + .get_caps = power_cppc_get_capabilities +}; + +RTE_POWER_REGISTER_OPS(cppc_ops); diff --git a/lib/power/power_cppc_cpufreq.h b/drivers/power/cppc/cppc_cpufreq.h similarity index 97% rename from lib/power/power_cppc_cpufreq.h rename to drivers/power/cppc/cppc_cpufreq.h index f4121b237e..64a766145a 100644 --- a/lib/power/power_cppc_cpufreq.h +++ b/drivers/power/cppc/cppc_cpufreq.h @@ -3,15 +3,15 @@ * Copyright(c) 2021 Arm Limited */ -#ifndef _POWER_CPPC_CPUFREQ_H -#define _POWER_CPPC_CPUFREQ_H +#ifndef _CPPC_CPUFREQ_H +#define _CPPC_CPUFREQ_H /** * @file * RTE Power Management via userspace CPPC cpufreq */ -#include "rte_power.h" +#include "rte_power_cpufreq_api.h" /** * Check if CPPC power management is supported. @@ -215,4 +215,4 @@ int power_cppc_disable_turbo(unsigned int lcore_id); int power_cppc_get_capabilities(unsigned int lcore_id, struct rte_power_core_capabilities *caps); -#endif /* _POWER_CPPC_CPUFREQ_H */ +#endif /* _CPPC_CPUFREQ_H */ diff --git a/drivers/power/cppc/meson.build b/drivers/power/cppc/meson.build new file mode 100644 index 0000000000..f1948cd424 --- /dev/null +++ b/drivers/power/cppc/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +if not is_linux + build = false + reason = 'only supported on Linux' +endif +sources = files('cppc_cpufreq.c') + +deps += ['power'] diff --git a/lib/power/guest_channel.c b/drivers/power/kvm_vm/guest_channel.c similarity index 100% rename from lib/power/guest_channel.c rename to drivers/power/kvm_vm/guest_channel.c diff --git a/lib/power/guest_channel.h b/drivers/power/kvm_vm/guest_channel.h similarity index 100% rename from lib/power/guest_channel.h rename to drivers/power/kvm_vm/guest_channel.h diff --git a/lib/power/power_kvm_vm.c b/drivers/power/kvm_vm/kvm_vm.c similarity index 82% rename from lib/power/power_kvm_vm.c rename to drivers/power/kvm_vm/kvm_vm.c index f15be8fac5..a1342dcd8b 100644 --- a/lib/power/power_kvm_vm.c +++ b/drivers/power/kvm_vm/kvm_vm.c @@ -9,7 +9,7 @@ #include "rte_power_guest_channel.h" #include "guest_channel.h" #include "power_common.h" -#include "power_kvm_vm.h" +#include "kvm_vm.h" #define FD_PATH "/dev/virtio-ports/virtio.serial.port.poweragent" @@ -137,3 +137,23 @@ int power_kvm_vm_get_capabilities(__rte_unused unsigned int lcore_id, POWER_LOG(ERR, "rte_power_get_capabilities is not implemented for Virtual Machine Power Management"); return -ENOTSUP; } + +static struct rte_power_core_ops kvm_vm_ops = { + .name = "kvm-vm", + .init = power_kvm_vm_init, + .exit = power_kvm_vm_exit, + .check_env_support = power_kvm_vm_check_supported, + .get_avail_freqs = power_kvm_vm_freqs, + .get_freq = power_kvm_vm_get_freq, + .set_freq = power_kvm_vm_set_freq, + .freq_down = power_kvm_vm_freq_down, + .freq_up = power_kvm_vm_freq_up, + .freq_max = power_kvm_vm_freq_max, + .freq_min = power_kvm_vm_freq_min, + .turbo_status = power_kvm_vm_turbo_status, + .enable_turbo = power_kvm_vm_enable_turbo, + .disable_turbo = power_kvm_vm_disable_turbo, + .get_caps = power_kvm_vm_get_capabilities +}; + +RTE_POWER_REGISTER_OPS(kvm_vm_ops); diff --git a/lib/power/power_kvm_vm.h b/drivers/power/kvm_vm/kvm_vm.h similarity index 98% rename from lib/power/power_kvm_vm.h rename to drivers/power/kvm_vm/kvm_vm.h index 303fcc041b..8b92054076 100644 --- a/lib/power/power_kvm_vm.h +++ b/drivers/power/kvm_vm/kvm_vm.h @@ -2,15 +2,15 @@ * Copyright(c) 2010-2014 Intel Corporation */ -#ifndef _POWER_KVM_VM_H -#define _POWER_KVM_VM_H +#ifndef _KVM_VM_H +#define _KVM_VM_H /** * @file * RTE Power Management KVM VM */ -#include "rte_power.h" +#include "rte_power_cpufreq_api.h" /** * Check if KVM power management is supported. diff --git a/drivers/power/kvm_vm/meson.build b/drivers/power/kvm_vm/meson.build new file mode 100644 index 0000000000..405524ce7c --- /dev/null +++ b/drivers/power/kvm_vm/meson.build @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(C) 2024 Advanced Micro Devices, Inc. +# + +if not is_linux + build = false + reason = 'only supported on Linux' + subdir_done() +endif + +sources = files( + 'guest_channel.c', + 'kvm_vm.c', +) + +deps += ['power'] diff --git a/drivers/power/meson.build b/drivers/power/meson.build new file mode 100644 index 0000000000..8c7215c639 --- /dev/null +++ b/drivers/power/meson.build @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +drivers = [ + 'acpi', + 'amd_pstate', + 'cppc', + 'kvm_vm', + 'pstate' +] + +std_deps = ['power'] diff --git a/drivers/power/pstate/meson.build b/drivers/power/pstate/meson.build new file mode 100644 index 0000000000..9cd47833fb --- /dev/null +++ b/drivers/power/pstate/meson.build @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +if not is_linux + build = false + reason = 'only supported on Linux' +endif +sources = files('pstate_cpufreq.c') + +deps += ['power'] diff --git a/lib/power/power_pstate_cpufreq.c b/drivers/power/pstate/pstate_cpufreq.c similarity index 96% rename from lib/power/power_pstate_cpufreq.c rename to drivers/power/pstate/pstate_cpufreq.c index 2343121621..c32b1adabc 100644 --- a/lib/power/power_pstate_cpufreq.c +++ b/drivers/power/pstate/pstate_cpufreq.c @@ -15,7 +15,7 @@ #include #include "rte_power_pmd_mgmt.h" -#include "power_pstate_cpufreq.h" +#include "pstate_cpufreq.h" #include "power_common.h" /* macros used for rounding frequency to nearest 100000 */ @@ -888,3 +888,23 @@ int power_pstate_get_capabilities(unsigned int lcore_id, return 0; } + +static struct rte_power_core_ops pstate_ops = { + .name = "pstate", + .init = power_pstate_cpufreq_init, + .exit = power_pstate_cpufreq_exit, + .check_env_support = power_pstate_cpufreq_check_supported, + .get_avail_freqs = power_pstate_cpufreq_freqs, + .get_freq = power_pstate_cpufreq_get_freq, + .set_freq = power_pstate_cpufreq_set_freq, + .freq_down = power_pstate_cpufreq_freq_down, + .freq_up = power_pstate_cpufreq_freq_up, + .freq_max = power_pstate_cpufreq_freq_max, + .freq_min = power_pstate_cpufreq_freq_min, + .turbo_status = power_pstate_turbo_status, + .enable_turbo = power_pstate_enable_turbo, + .disable_turbo = power_pstate_disable_turbo, + .get_caps = power_pstate_get_capabilities +}; + +RTE_POWER_REGISTER_OPS(pstate_ops); diff --git a/lib/power/power_pstate_cpufreq.h b/drivers/power/pstate/pstate_cpufreq.h similarity index 98% rename from lib/power/power_pstate_cpufreq.h rename to drivers/power/pstate/pstate_cpufreq.h index 7bf64a518c..5fddb40280 100644 --- a/lib/power/power_pstate_cpufreq.h +++ b/drivers/power/pstate/pstate_cpufreq.h @@ -2,15 +2,15 @@ * Copyright(c) 2018 Intel Corporation */ -#ifndef _POWER_PSTATE_CPUFREQ_H -#define _POWER_PSTATE_CPUFREQ_H +#ifndef _PSTATE_CPUFREQ_H +#define _PSTATE_CPUFREQ_H /** * @file * RTE Power Management via Intel Pstate driver */ -#include "rte_power.h" +#include "rte_power_cpufreq_api.h" /** * Check if pstate power management is supported. diff --git a/lib/power/meson.build b/lib/power/meson.build index b8426589b2..d6b86ea19c 100644 --- a/lib/power/meson.build +++ b/lib/power/meson.build @@ -12,20 +12,15 @@ if not is_linux reason = 'only supported on Linux' endif sources = files( - 'guest_channel.c', - 'power_acpi_cpufreq.c', - 'power_amd_pstate_cpufreq.c', 'power_common.c', - 'power_cppc_cpufreq.c', - 'power_kvm_vm.c', 'power_intel_uncore.c', - 'power_pstate_cpufreq.c', 'rte_power.c', 'rte_power_uncore.c', 'rte_power_pmd_mgmt.c', ) headers = files( 'rte_power.h', + 'rte_power_cpufreq_api.h', 'rte_power_guest_channel.h', 'rte_power_pmd_mgmt.h', 'rte_power_uncore.h', diff --git a/lib/power/power_common.c b/lib/power/power_common.c index 590986d5ef..6c06411e8b 100644 --- a/lib/power/power_common.c +++ b/lib/power/power_common.c @@ -12,7 +12,7 @@ #include "power_common.h" -RTE_LOG_REGISTER_DEFAULT(power_logtype, INFO); +RTE_LOG_REGISTER_DEFAULT(rte_power_logtype, INFO); #define POWER_SYSFILE_SCALING_DRIVER \ "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_driver" diff --git a/lib/power/power_common.h b/lib/power/power_common.h index 83f742f42a..767686ee12 100644 --- a/lib/power/power_common.h +++ b/lib/power/power_common.h @@ -6,12 +6,13 @@ #define _POWER_COMMON_H_ #include +#include #include #define RTE_POWER_INVALID_FREQ_INDEX (~0) -extern int power_logtype; -#define RTE_LOGTYPE_POWER power_logtype +extern int rte_power_logtype; +#define RTE_LOGTYPE_POWER rte_power_logtype #define POWER_LOG(level, ...) \ RTE_LOG_LINE(level, POWER, "" __VA_ARGS__) @@ -23,13 +24,24 @@ extern int power_logtype; #endif /* check if scaling driver matches one we want */ +__rte_internal int cpufreq_check_scaling_driver(const char *driver); + +__rte_internal int power_set_governor(unsigned int lcore_id, const char *new_governor, char *orig_governor, size_t orig_governor_len); + +__rte_internal int open_core_sysfs_file(FILE **f, const char *mode, const char *format, ...) __rte_format_printf(3, 4); + +__rte_internal int read_core_sysfs_u32(FILE *f, uint32_t *val); + +__rte_internal int read_core_sysfs_s(FILE *f, char *buf, unsigned int len); + +__rte_internal int write_core_sysfs_s(FILE *f, const char *str); #endif /* _POWER_COMMON_H_ */ diff --git a/lib/power/rte_power.c b/lib/power/rte_power.c index 36c3f3da98..fbee9033f2 100644 --- a/lib/power/rte_power.c +++ b/lib/power/rte_power.c @@ -8,153 +8,86 @@ #include #include "rte_power.h" -#include "power_acpi_cpufreq.h" -#include "power_cppc_cpufreq.h" #include "power_common.h" -#include "power_kvm_vm.h" -#include "power_pstate_cpufreq.h" -#include "power_amd_pstate_cpufreq.h" -enum power_management_env global_default_env = PM_ENV_NOT_SET; +static enum power_management_env global_default_env = PM_ENV_NOT_SET; +static struct rte_power_core_ops *global_power_core_ops; static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER; +static RTE_TAILQ_HEAD(, rte_power_core_ops) core_ops_list = + TAILQ_HEAD_INITIALIZER(core_ops_list); -/* function pointers */ -rte_power_freqs_t rte_power_freqs = NULL; -rte_power_get_freq_t rte_power_get_freq = NULL; -rte_power_set_freq_t rte_power_set_freq = NULL; -rte_power_freq_change_t rte_power_freq_up = NULL; -rte_power_freq_change_t rte_power_freq_down = NULL; -rte_power_freq_change_t rte_power_freq_max = NULL; -rte_power_freq_change_t rte_power_freq_min = NULL; -rte_power_freq_change_t rte_power_turbo_status; -rte_power_freq_change_t rte_power_freq_enable_turbo; -rte_power_freq_change_t rte_power_freq_disable_turbo; -rte_power_get_capabilities_t rte_power_get_capabilities; - -static void -reset_power_function_ptrs(void) + +const char *power_env_str[] = { + "not set", + "acpi", + "kvm-vm", + "pstate", + "cppc", + "amd-pstate" +}; + +/* register the ops struct in rte_power_core_ops, return 0 on success. */ +int +rte_power_register_ops(struct rte_power_core_ops *driver_ops) { - rte_power_freqs = NULL; - rte_power_get_freq = NULL; - rte_power_set_freq = NULL; - rte_power_freq_up = NULL; - rte_power_freq_down = NULL; - rte_power_freq_max = NULL; - rte_power_freq_min = NULL; - rte_power_turbo_status = NULL; - rte_power_freq_enable_turbo = NULL; - rte_power_freq_disable_turbo = NULL; - rte_power_get_capabilities = NULL; + if (!driver_ops->init || !driver_ops->exit || + !driver_ops->check_env_support || !driver_ops->get_avail_freqs || + !driver_ops->get_freq || !driver_ops->set_freq || + !driver_ops->freq_up || !driver_ops->freq_down || + !driver_ops->freq_max || !driver_ops->freq_min || + !driver_ops->turbo_status || !driver_ops->enable_turbo || + !driver_ops->disable_turbo || !driver_ops->get_caps) { + POWER_LOG(ERR, "Missing callbacks while registering power ops"); + return -EINVAL; + } + + TAILQ_INSERT_TAIL(&core_ops_list, driver_ops, next); + + return 0; } int rte_power_check_env_supported(enum power_management_env env) { - switch (env) { - case PM_ENV_ACPI_CPUFREQ: - return power_acpi_cpufreq_check_supported(); - case PM_ENV_PSTATE_CPUFREQ: - return power_pstate_cpufreq_check_supported(); - case PM_ENV_KVM_VM: - return power_kvm_vm_check_supported(); - case PM_ENV_CPPC_CPUFREQ: - return power_cppc_cpufreq_check_supported(); - case PM_ENV_AMD_PSTATE_CPUFREQ: - return power_amd_pstate_cpufreq_check_supported(); - default: - rte_errno = EINVAL; - return -1; - } + struct rte_power_core_ops *ops; + + if (env >= RTE_DIM(power_env_str)) + return 0; + + RTE_TAILQ_FOREACH(ops, &core_ops_list, next) + if (strncmp(ops->name, power_env_str[env], + RTE_POWER_DRIVER_NAMESZ) == 0) + return ops->check_env_support(); + + return 0; } int rte_power_set_env(enum power_management_env env) { + struct rte_power_core_ops *ops; + int ret = -1; + rte_spinlock_lock(&global_env_cfg_lock); if (global_default_env != PM_ENV_NOT_SET) { POWER_LOG(ERR, "Power Management Environment already set."); - rte_spinlock_unlock(&global_env_cfg_lock); - return -1; - } - - int ret = 0; - - if (env == PM_ENV_ACPI_CPUFREQ) { - rte_power_freqs = power_acpi_cpufreq_freqs; - rte_power_get_freq = power_acpi_cpufreq_get_freq; - rte_power_set_freq = power_acpi_cpufreq_set_freq; - rte_power_freq_up = power_acpi_cpufreq_freq_up; - rte_power_freq_down = power_acpi_cpufreq_freq_down; - rte_power_freq_min = power_acpi_cpufreq_freq_min; - rte_power_freq_max = power_acpi_cpufreq_freq_max; - rte_power_turbo_status = power_acpi_turbo_status; - rte_power_freq_enable_turbo = power_acpi_enable_turbo; - rte_power_freq_disable_turbo = power_acpi_disable_turbo; - rte_power_get_capabilities = power_acpi_get_capabilities; - } else if (env == PM_ENV_KVM_VM) { - rte_power_freqs = power_kvm_vm_freqs; - rte_power_get_freq = power_kvm_vm_get_freq; - rte_power_set_freq = power_kvm_vm_set_freq; - rte_power_freq_up = power_kvm_vm_freq_up; - rte_power_freq_down = power_kvm_vm_freq_down; - rte_power_freq_min = power_kvm_vm_freq_min; - rte_power_freq_max = power_kvm_vm_freq_max; - rte_power_turbo_status = power_kvm_vm_turbo_status; - rte_power_freq_enable_turbo = power_kvm_vm_enable_turbo; - rte_power_freq_disable_turbo = power_kvm_vm_disable_turbo; - rte_power_get_capabilities = power_kvm_vm_get_capabilities; - } else if (env == PM_ENV_PSTATE_CPUFREQ) { - rte_power_freqs = power_pstate_cpufreq_freqs; - rte_power_get_freq = power_pstate_cpufreq_get_freq; - rte_power_set_freq = power_pstate_cpufreq_set_freq; - rte_power_freq_up = power_pstate_cpufreq_freq_up; - rte_power_freq_down = power_pstate_cpufreq_freq_down; - rte_power_freq_min = power_pstate_cpufreq_freq_min; - rte_power_freq_max = power_pstate_cpufreq_freq_max; - rte_power_turbo_status = power_pstate_turbo_status; - rte_power_freq_enable_turbo = power_pstate_enable_turbo; - rte_power_freq_disable_turbo = power_pstate_disable_turbo; - rte_power_get_capabilities = power_pstate_get_capabilities; - - } else if (env == PM_ENV_CPPC_CPUFREQ) { - rte_power_freqs = power_cppc_cpufreq_freqs; - rte_power_get_freq = power_cppc_cpufreq_get_freq; - rte_power_set_freq = power_cppc_cpufreq_set_freq; - rte_power_freq_up = power_cppc_cpufreq_freq_up; - rte_power_freq_down = power_cppc_cpufreq_freq_down; - rte_power_freq_min = power_cppc_cpufreq_freq_min; - rte_power_freq_max = power_cppc_cpufreq_freq_max; - rte_power_turbo_status = power_cppc_turbo_status; - rte_power_freq_enable_turbo = power_cppc_enable_turbo; - rte_power_freq_disable_turbo = power_cppc_disable_turbo; - rte_power_get_capabilities = power_cppc_get_capabilities; - } else if (env == PM_ENV_AMD_PSTATE_CPUFREQ) { - rte_power_freqs = power_amd_pstate_cpufreq_freqs; - rte_power_get_freq = power_amd_pstate_cpufreq_get_freq; - rte_power_set_freq = power_amd_pstate_cpufreq_set_freq; - rte_power_freq_up = power_amd_pstate_cpufreq_freq_up; - rte_power_freq_down = power_amd_pstate_cpufreq_freq_down; - rte_power_freq_min = power_amd_pstate_cpufreq_freq_min; - rte_power_freq_max = power_amd_pstate_cpufreq_freq_max; - rte_power_turbo_status = power_amd_pstate_turbo_status; - rte_power_freq_enable_turbo = power_amd_pstate_enable_turbo; - rte_power_freq_disable_turbo = power_amd_pstate_disable_turbo; - rte_power_get_capabilities = power_amd_pstate_get_capabilities; - } else { - POWER_LOG(ERR, "Invalid Power Management Environment(%d) set", - env); - ret = -1; + goto out; } - if (ret == 0) - global_default_env = env; - else { - global_default_env = PM_ENV_NOT_SET; - reset_power_function_ptrs(); - } + RTE_TAILQ_FOREACH(ops, &core_ops_list, next) + if (strncmp(ops->name, power_env_str[env], + RTE_POWER_DRIVER_NAMESZ) == 0) { + global_power_core_ops = ops; + global_default_env = env; + ret = 0; + goto out; + } + POWER_LOG(ERR, "Invalid Power Management Environment(%d) set", + env); +out: rte_spinlock_unlock(&global_env_cfg_lock); return ret; } @@ -164,94 +97,65 @@ rte_power_unset_env(void) { rte_spinlock_lock(&global_env_cfg_lock); global_default_env = PM_ENV_NOT_SET; - reset_power_function_ptrs(); + global_power_core_ops = NULL; rte_spinlock_unlock(&global_env_cfg_lock); } enum power_management_env -rte_power_get_env(void) { +rte_power_get_env(void) +{ return global_default_env; } +struct rte_power_core_ops * +rte_power_get_core_ops(void) +{ + RTE_ASSERT(global_power_core_ops != NULL); + + return global_power_core_ops; +} + int rte_power_init(unsigned int lcore_id) { - int ret = -1; + struct rte_power_core_ops *ops; + uint8_t env; - switch (global_default_env) { - case PM_ENV_ACPI_CPUFREQ: - return power_acpi_cpufreq_init(lcore_id); - case PM_ENV_KVM_VM: - return power_kvm_vm_init(lcore_id); - case PM_ENV_PSTATE_CPUFREQ: - return power_pstate_cpufreq_init(lcore_id); - case PM_ENV_CPPC_CPUFREQ: - return power_cppc_cpufreq_init(lcore_id); - case PM_ENV_AMD_PSTATE_CPUFREQ: - return power_amd_pstate_cpufreq_init(lcore_id); - default: - POWER_LOG(INFO, "Env isn't set yet!"); - } + if (global_default_env != PM_ENV_NOT_SET) + return global_power_core_ops->init(lcore_id); - /* Auto detect Environment */ - POWER_LOG(INFO, "Attempting to initialise ACPI cpufreq power management..."); - ret = power_acpi_cpufreq_init(lcore_id); - if (ret == 0) { - rte_power_set_env(PM_ENV_ACPI_CPUFREQ); - goto out; - } + POWER_LOG(INFO, "Env isn't set yet!"); - POWER_LOG(INFO, "Attempting to initialise PSTAT power management..."); - ret = power_pstate_cpufreq_init(lcore_id); - if (ret == 0) { - rte_power_set_env(PM_ENV_PSTATE_CPUFREQ); - goto out; + /* Auto detect Environment */ + RTE_TAILQ_FOREACH(ops, &core_ops_list, next) { + POWER_LOG(INFO, + "Attempting to initialise %s cpufreq power management...", + ops->name); + for (env = 0; env < RTE_DIM(power_env_str); env++) { + if ((strncmp(ops->name, power_env_str[env], + RTE_POWER_DRIVER_NAMESZ) == 0) && + (ops->init(lcore_id) == 0)) { + rte_power_set_env(env); + return 0; + } + } } - POWER_LOG(INFO, "Attempting to initialise AMD PSTATE power management..."); - ret = power_amd_pstate_cpufreq_init(lcore_id); - if (ret == 0) { - rte_power_set_env(PM_ENV_AMD_PSTATE_CPUFREQ); - goto out; - } + POWER_LOG(ERR, + "Unable to set Power Management Environment for lcore %u", + lcore_id); - POWER_LOG(INFO, "Attempting to initialise CPPC power management..."); - ret = power_cppc_cpufreq_init(lcore_id); - if (ret == 0) { - rte_power_set_env(PM_ENV_CPPC_CPUFREQ); - goto out; - } - - POWER_LOG(INFO, "Attempting to initialise VM power management..."); - ret = power_kvm_vm_init(lcore_id); - if (ret == 0) { - rte_power_set_env(PM_ENV_KVM_VM); - goto out; - } - POWER_LOG(ERR, "Unable to set Power Management Environment for lcore " - "%u", lcore_id); -out: - return ret; + return -1; } int rte_power_exit(unsigned int lcore_id) { - switch (global_default_env) { - case PM_ENV_ACPI_CPUFREQ: - return power_acpi_cpufreq_exit(lcore_id); - case PM_ENV_KVM_VM: - return power_kvm_vm_exit(lcore_id); - case PM_ENV_PSTATE_CPUFREQ: - return power_pstate_cpufreq_exit(lcore_id); - case PM_ENV_CPPC_CPUFREQ: - return power_cppc_cpufreq_exit(lcore_id); - case PM_ENV_AMD_PSTATE_CPUFREQ: - return power_amd_pstate_cpufreq_exit(lcore_id); - default: - POWER_LOG(ERR, "Environment has not been set, unable to exit gracefully"); + if (global_default_env != PM_ENV_NOT_SET) + return global_power_core_ops->exit(lcore_id); - } - return -1; + POWER_LOG(ERR, + "Environment has not been set, unable to exit gracefully"); + return -1; } diff --git a/lib/power/rte_power.h b/lib/power/rte_power.h index 4fa4afe399..d77d285c18 100644 --- a/lib/power/rte_power.h +++ b/lib/power/rte_power.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2010-2014 Intel Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. */ #ifndef _RTE_POWER_H @@ -14,14 +15,21 @@ #include #include +#include "rte_power_cpufreq_api.h" + #ifdef __cplusplus extern "C" { #endif /* Power Management Environment State */ -enum power_management_env {PM_ENV_NOT_SET, PM_ENV_ACPI_CPUFREQ, PM_ENV_KVM_VM, - PM_ENV_PSTATE_CPUFREQ, PM_ENV_CPPC_CPUFREQ, - PM_ENV_AMD_PSTATE_CPUFREQ}; +enum power_management_env { + PM_ENV_NOT_SET = 0, + PM_ENV_ACPI_CPUFREQ, + PM_ENV_KVM_VM, + PM_ENV_PSTATE_CPUFREQ, + PM_ENV_CPPC_CPUFREQ, + PM_ENV_AMD_PSTATE_CPUFREQ +}; /** * Check if a specific power management environment type is supported on a @@ -66,6 +74,15 @@ void rte_power_unset_env(void); */ enum power_management_env rte_power_get_env(void); +/** + * @internal Get the power ops struct from its index. + * + * @return + * The pointer to the ops struct in the table if registered. + */ +struct rte_power_core_ops * +rte_power_get_core_ops(void); + /** * Initialize power management for a specific lcore. If rte_power_set_env() has * not been called then an auto-detect of the environment will start and @@ -108,10 +125,13 @@ int rte_power_exit(unsigned int lcore_id); * @return * The number of available frequencies. */ -typedef uint32_t (*rte_power_freqs_t)(unsigned int lcore_id, uint32_t *freqs, - uint32_t num); +static inline uint32_t +rte_power_freqs(unsigned int lcore_id, uint32_t *freqs, uint32_t n) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); -extern rte_power_freqs_t rte_power_freqs; + return ops->get_avail_freqs(lcore_id, freqs, n); +} /** * Return the current index of available frequencies of a specific lcore. @@ -124,9 +144,13 @@ extern rte_power_freqs_t rte_power_freqs; * @return * The current index of available frequencies. */ -typedef uint32_t (*rte_power_get_freq_t)(unsigned int lcore_id); +static inline uint32_t +rte_power_get_freq(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); -extern rte_power_get_freq_t rte_power_get_freq; + return ops->get_freq(lcore_id); +} /** * Set the new frequency for a specific lcore by indicating the index of @@ -144,82 +168,101 @@ extern rte_power_get_freq_t rte_power_get_freq; * - 0 on success without frequency changed. * - Negative on error. */ -typedef int (*rte_power_set_freq_t)(unsigned int lcore_id, uint32_t index); - -extern rte_power_set_freq_t rte_power_set_freq; +static inline uint32_t +rte_power_set_freq(unsigned int lcore_id, uint32_t index) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); -/** - * Function pointer definition for generic frequency change functions. Review - * each environments specific documentation for usage. - * - * @param lcore_id - * lcore id. - * - * @return - * - 1 on success with frequency changed. - * - 0 on success without frequency changed. - * - Negative on error. - */ -typedef int (*rte_power_freq_change_t)(unsigned int lcore_id); + return ops->set_freq(lcore_id, index); +} /** * Scale up the frequency of a specific lcore according to the available * frequencies. * Review each environments specific documentation for usage. */ -extern rte_power_freq_change_t rte_power_freq_up; +static inline int +rte_power_freq_up(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->freq_up(lcore_id); +} /** * Scale down the frequency of a specific lcore according to the available * frequencies. * Review each environments specific documentation for usage. */ -extern rte_power_freq_change_t rte_power_freq_down; +static inline int +rte_power_freq_down(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->freq_down(lcore_id); +} /** * Scale up the frequency of a specific lcore to the highest according to the * available frequencies. * Review each environments specific documentation for usage. */ -extern rte_power_freq_change_t rte_power_freq_max; +static inline int +rte_power_freq_max(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->freq_max(lcore_id); +} /** * Scale down the frequency of a specific lcore to the lowest according to the * available frequencies. * Review each environments specific documentation for usage.. */ -extern rte_power_freq_change_t rte_power_freq_min; +static inline int +rte_power_freq_min(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->freq_min(lcore_id); +} /** * Query the Turbo Boost status of a specific lcore. * Review each environments specific documentation for usage.. */ -extern rte_power_freq_change_t rte_power_turbo_status; +static inline int +rte_power_turbo_status(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->turbo_status(lcore_id); +} /** * Enable Turbo Boost for this lcore. * Review each environments specific documentation for usage.. */ -extern rte_power_freq_change_t rte_power_freq_enable_turbo; +static inline int +rte_power_freq_enable_turbo(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); + + return ops->enable_turbo(lcore_id); +} /** * Disable Turbo Boost for this lcore. * Review each environments specific documentation for usage.. */ -extern rte_power_freq_change_t rte_power_freq_disable_turbo; +static inline int +rte_power_freq_disable_turbo(unsigned int lcore_id) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); -/** - * Power capabilities summary. - */ -struct rte_power_core_capabilities { - union { - uint64_t capabilities; - struct { - uint64_t turbo:1; /**< Turbo can be enabled. */ - uint64_t priority:1; /**< SST-BF high freq core */ - }; - }; -}; + return ops->disable_turbo(lcore_id); +} /** * Returns power capabilities for a specific lcore. @@ -235,10 +278,14 @@ struct rte_power_core_capabilities { * - 0 on success. * - Negative on error. */ -typedef int (*rte_power_get_capabilities_t)(unsigned int lcore_id, - struct rte_power_core_capabilities *caps); +static inline int +rte_power_get_capabilities(unsigned int lcore_id, + struct rte_power_core_capabilities *caps) +{ + struct rte_power_core_ops *ops = rte_power_get_core_ops(); -extern rte_power_get_capabilities_t rte_power_get_capabilities; + return ops->get_caps(lcore_id, caps); +} #ifdef __cplusplus } diff --git a/lib/power/rte_power_cpufreq_api.h b/lib/power/rte_power_cpufreq_api.h new file mode 100644 index 0000000000..526372e0d4 --- /dev/null +++ b/lib/power/rte_power_cpufreq_api.h @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. + */ + +#ifndef _RTE_POWER_CPUFREQ_API_H +#define _RTE_POWER_CPUFREQ_API_H + +/** + * @file + * RTE Power Management + */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RTE_POWER_DRIVER_NAMESZ 24 + +/** + * Initialize power management for a specific lcore. If rte_power_set_env() has + * not been called then an auto-detect of the environment will start and + * initialise the corresponding resources. + * + * @param lcore_id + * lcore id. + * + * @return + * - 0 on success. + * - Negative on error. + */ +typedef int (*rte_power_cpufreq_init_t)(unsigned int lcore_id); + +/** + * Exit power management on a specific lcore. This will call the environment + * dependent exit function. + * + * @param lcore_id + * lcore id. + * + * @return + * - 0 on success. + * - Negative on error. + */ +typedef int (*rte_power_cpufreq_exit_t)(unsigned int lcore_id); + +/** + * Check if a specific power management environment type is supported on a + * currently running system. + * + * @return + * - 1 if supported + * - 0 if unsupported + * - -1 if error, with rte_errno indicating reason for error. + */ +typedef int (*rte_power_check_env_support_t)(void); + +/** + * Get the available frequencies of a specific lcore. + * Function pointer definition. Review each environments + * specific documentation for usage. + * + * @param lcore_id + * lcore id. + * @param freqs + * The buffer array to save the frequencies. + * @param num + * The number of frequencies to get. + * + * @return + * The number of available frequencies. + */ +typedef uint32_t (*rte_power_freqs_t)(unsigned int lcore_id, uint32_t *freqs, + uint32_t num); + +/** + * Return the current index of available frequencies of a specific lcore. + * Function pointer definition. Review each environments + * specific documentation for usage. + * + * @param lcore_id + * lcore id. + * + * @return + * The current index of available frequencies. + */ +typedef uint32_t (*rte_power_get_freq_t)(unsigned int lcore_id); + +/** + * Set the new frequency for a specific lcore by indicating the index of + * available frequencies. + * Function pointer definition. Review each environments + * specific documentation for usage. + * + * @param lcore_id + * lcore id. + * @param index + * The index of available frequencies. + * + * @return + * - 1 on success with frequency changed. + * - 0 on success without frequency changed. + * - Negative on error. + */ +typedef int (*rte_power_set_freq_t)(unsigned int lcore_id, uint32_t index); + +/** + * Function pointer definition for generic frequency change functions. Review + * each environments specific documentation for usage. + * + * @param lcore_id + * lcore id. + * + * @return + * - 1 on success with frequency changed. + * - 0 on success without frequency changed. + * - Negative on error. + */ +typedef int (*rte_power_freq_change_t)(unsigned int lcore_id); + +/** + * Function pointer definition for generic frequency change functions. Review + * each environments specific documentation for usage. + * + * @param lcore_id + * lcore id. + * + * @return + * - 1 on success with frequency changed. + * - 0 on success without frequency changed. + * - Negative on error. + */ + +/** + * Power capabilities summary. + */ +struct rte_power_core_capabilities { + union { + uint64_t capabilities; + struct { + uint64_t turbo:1; /**< Turbo can be enabled. */ + uint64_t priority:1; /**< SST-BF high freq core */ + }; + }; +}; + +typedef int (*rte_power_get_capabilities_t)(unsigned int lcore_id, + struct rte_power_core_capabilities *caps); + +/** Structure defining core power operations structure */ +struct rte_power_core_ops { + RTE_TAILQ_ENTRY(rte_power_core_ops) next; /**< Next in list. */ + char name[RTE_POWER_DRIVER_NAMESZ]; /**< power mgmt driver. */ + rte_power_cpufreq_init_t init; /**< Initialize power management. */ + rte_power_cpufreq_exit_t exit; /**< Exit power management. */ + rte_power_check_env_support_t check_env_support;/**< verify env is supported. */ + rte_power_freqs_t get_avail_freqs; /**< Get the available frequencies. */ + rte_power_get_freq_t get_freq; /**< Get frequency index. */ + rte_power_set_freq_t set_freq; /**< Set frequency index. */ + rte_power_freq_change_t freq_up; /**< Scale up frequency. */ + rte_power_freq_change_t freq_down; /**< Scale down frequency. */ + rte_power_freq_change_t freq_max; /**< Scale up frequency to highest. */ + rte_power_freq_change_t freq_min; /**< Scale up frequency to lowest. */ + rte_power_freq_change_t turbo_status; /**< Get Turbo status. */ + rte_power_freq_change_t enable_turbo; /**< Enable Turbo. */ + rte_power_freq_change_t disable_turbo; /**< Disable Turbo. */ + rte_power_get_capabilities_t get_caps; /**< power capabilities. */ +}; + +/** + * Register power cpu frequency operations. + * + * @param ops + * Pointer to an ops structure to register. + * @return + * - >=0: Success; return the index of the ops struct in the table. + * - -EINVAL - error while registering ops struct. + */ +__rte_internal +int rte_power_register_ops(struct rte_power_core_ops *ops); + +/** + * Macro to statically register the ops of a cpufreq driver. + */ +#define RTE_POWER_REGISTER_OPS(ops) \ +RTE_INIT(power_hdlr_init_##ops) \ +{ \ + rte_power_register_ops(&ops); \ +} + +/** + * @internal Get the power ops struct from its index. + * + * @return + * The pointer to the ops struct in the table if registered. + */ +struct rte_power_core_ops * +rte_power_get_core_ops(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/power/version.map b/lib/power/version.map index c9a226614e..a46dd8adbf 100644 --- a/lib/power/version.map +++ b/lib/power/version.map @@ -51,4 +51,18 @@ EXPERIMENTAL { rte_power_set_uncore_env; rte_power_uncore_freqs; rte_power_unset_uncore_env; + # added in 24.11 + rte_power_logtype; +}; + +INTERNAL { + global: + + rte_power_register_ops; + cpufreq_check_scaling_driver; + power_set_governor; + open_core_sysfs_file; + read_core_sysfs_u32; + read_core_sysfs_s; + write_core_sysfs_s; };