From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2502545C00; Mon, 28 Oct 2024 20:56:34 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 109F6427E2; Mon, 28 Oct 2024 20:56:34 +0100 (CET) Received: from NAM11-DM6-obe.outbound.protection.outlook.com (mail-dm6nam11on2084.outbound.protection.outlook.com [40.107.223.84]) by mails.dpdk.org (Postfix) with ESMTP id DF39742C24 for ; Mon, 28 Oct 2024 20:56:23 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=LQgRhsCaPR2aOxPGeYrJLKxqjt6Zh/KWM7kI53yVJBOKVO7BhS0vNZu8LJQCvwOrPOlWaJKIIJbWzSgidMDq5UN0FH+13K9O0Ed0oeKU/q5CBGItnmTVPNIl1DC+sv7JoCmxABAWC2oQxKo2w8g6MU5Y2RCzBe4AK48EJd98lvAOfVUOdGcw8fwbDZ63z1pk2dxeekWD2Zk/JBBRweqWj3ESn12OVT0nySlp6Mf6KSIUS2mFpRGkY3SKVEvg/2tz8i0FG4hi8s+475Mee0tA+GBK2rFtqMthiXE9LFoAjvR6TpWRmNoUDGLOlTzqRTxbCcTKSWI9vkBMtnRN7tq6Lw== 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=wjL/mlN9pS6VLjas+iCb7ZNdVyV8XA/J23K9vpMeMKc=; b=AcvbG/3VN0kUG7jgieYGe3sEx1jjWHIG19YFyp1L00ema30L1w2zdhIRsJzbYrIG0xawtunzz0JIC60z2qj3CT8dGSxqTjL8zXvfIzo40Lb3fzxzmr2F1r73EHRNaBSAYwaWczpF5QbMCXam4bUX9zsK5otrUbDVe8qOyFQcHDG55hPGUvGh/vhW70UHzCgc8Fn6EgIee/m/vcEF15GqfFKnd7MOoqC9nHPu3RArVD2ISoK5jidn07gXmznqhPEBCIcdOCxNXGTqvZ72ZE64SP4TFdY1WagvaO6C1uw2O9TzhFaIl2XS8P0TDyEqRTpOz/pVj478mF2jZ/UVkH7OPA== 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=wjL/mlN9pS6VLjas+iCb7ZNdVyV8XA/J23K9vpMeMKc=; b=txXft09jfCuhjjbIRaWf9p/vFfC7u1LUqDU1Vxvakam3VIuKbFiaOO5aQomi4eBdkQb7DG+l0SPTqxQQsQ36AkJAo8YS8rjVle2j1NYGAnIIv+oEZiUHOQNXtyBNHEh1/aygoA9UO0WDwQep+AQ1qrTdBQ4sd6SOU0qfCKTAlrU= Received: from BY5PR17CA0015.namprd17.prod.outlook.com (2603:10b6:a03:1b8::28) by PH8PR12MB7421.namprd12.prod.outlook.com (2603:10b6:510:22b::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8093.20; Mon, 28 Oct 2024 19:56:20 +0000 Received: from CO1PEPF000075EF.namprd03.prod.outlook.com (2603:10b6:a03:1b8:cafe::56) by BY5PR17CA0015.outlook.office365.com (2603:10b6:a03:1b8::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8093.22 via Frontend Transport; Mon, 28 Oct 2024 19:56:20 +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 CO1PEPF000075EF.mail.protection.outlook.com (10.167.249.38) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.8114.16 via Frontend Transport; Mon, 28 Oct 2024 19:56:19 +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; Mon, 28 Oct 2024 14:56:16 -0500 From: Sivaprasad Tummala To: , , , , , , , , CC: Subject: [PATCH v10 2/6] power: refactor uncore power management library Date: Mon, 28 Oct 2024 19:55:52 +0000 Message-ID: <20241028195556.450033-3-sivaprasad.tummala@amd.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241028195556.450033-1-sivaprasad.tummala@amd.com> References: <20241023051139.1066426-1-sivaprasad.tummala@amd.com> <20241028195556.450033-1-sivaprasad.tummala@amd.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Originating-IP: [10.180.168.240] X-ClientProxiedBy: SATLEXMB03.amd.com (10.181.40.144) To SATLEXMB04.amd.com (10.181.40.145) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CO1PEPF000075EF:EE_|PH8PR12MB7421:EE_ X-MS-Office365-Filtering-Correlation-Id: 74d8b1b0-6fdc-42e6-6ec2-08dcf78a979d X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|36860700013|376014|82310400026|1800799024; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?8ubK0MrBBd01vXIdIT5B8pJDfzcl0OCqa5BNbQfrvjbS2/eBA83k6bIEgKzQ?= =?us-ascii?Q?xWrjEBChRf2bLtkhiTjdpgIT+qQIX0clDo3cIunyq76f0wCXK69/clJPhoFw?= =?us-ascii?Q?im85CDVcdH6XXM2n6Zth9X3ELNNftYq5gr6sBCOuXNyeSVAbtz2UeT0vSC8G?= =?us-ascii?Q?huDKS4BJLVEsLoHdcoilGMESBlCH1CWI7cxywL6Wn/CYwRJXj76w1TbSQTyv?= =?us-ascii?Q?lSk6OnbtvJiDR/f0pkrrLqBzaqPkYwJEubCzn4yBQ6zsgtbWt51t3K6HrSQh?= =?us-ascii?Q?5V1xa4euK85U8H3BXUsfB+2t42CuVTplEwo/WCC6T9vsgcXV18seNVMBQjMp?= =?us-ascii?Q?QTIc7Dgq2BO/MP1Gx1vJFRwtEh1/4OMov77nReiHljEyfF3h6e9jIMPuIIrG?= =?us-ascii?Q?51MIT73rj5J1xLhrMqe0rOXmNOsHrf3wNZbbm9Thbu4XMXRdzr9U+qzHixML?= =?us-ascii?Q?o9VbGo1eQwTEDl20DcSBu5B2I5/m6zraXzpjzOts8MMCYR70eRU4JvSEOcbq?= =?us-ascii?Q?GD18581amFoO5uWLwwda9ffXFZ3tlotkM2jo8Fq7K8ytNKU0EitttlM9maBz?= =?us-ascii?Q?Pqh0JZeFu0RAGTpLKMUBhTHUSEIpdkFgRpGUXWrpLGlJ8HLPqn69hCfU4kIW?= =?us-ascii?Q?ysoyavq804fvMgPBGQnc5L7BTqlWqusOC8Pje/jrWHfPp5wSUBjTqQ1y3NKj?= =?us-ascii?Q?imtqzCF5FUUrR7175aQ2t7Y2dNqkdVkwy8EpNcWkUC0f/UpFHR0Jq1HS9dje?= =?us-ascii?Q?+7NnDR7vGMTsqunMRVatt8skMkjsFYGiFUHGIOTzJSjm8EXFUHqTd59sAwt3?= =?us-ascii?Q?CAI94eye/QvJkNrFoTJ3vx8DpT6WmEx67fYXru772l2cj32WdyFY+aZQz9Ow?= =?us-ascii?Q?cpcSMdeFdDdyhanGU1jEtvge+2D/iTGgzfxF52KO8Lm8KCuZUOvAtQK7Au9U?= =?us-ascii?Q?IvtwOC6m0TWfkS45o/Gf3/P8IZGMQFcR4RrtUtpI1WpGqcG8+/RKGzS3Pnqq?= =?us-ascii?Q?ClnLqn/C/NaJoBMRE+0YRofsVn7aZfxmLp7Pi/v4L1RYFMXcq2IuIVPMysjG?= =?us-ascii?Q?/L5hjDQb4AOzSWahFK9ndXOPB56OMJry8czvjD70JY5jFU+qhrQM9H4B1agF?= =?us-ascii?Q?G4vTAg05bPW/9VwAKPx3rLh+qmGUtTqjKdOPNeXOk07+7qUI1KCFdmreph+4?= =?us-ascii?Q?ysvn4wYDx2Q/YTSHEQE53PQqd8VqhO0VfjNene4z8gnhHjdEKm2IQLgDTMRE?= =?us-ascii?Q?jHDZtOidUuIFSzWfkKbA2JUiGJ7p5rD6eka6nODSjiH/UBgljiirV1ubt53H?= =?us-ascii?Q?dtVjnJ5UDkI/WPeO5EyWNC/OCrrQfsrvl6fCd3ZlTvEICwXd+oCdZgHlZuoI?= =?us-ascii?Q?Mj3hmxHr+eoJP62vWfWa3rxQAEndKFhV0nwThgG9i/0o1HQWEw=3D=3D?= 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)(36860700013)(376014)(82310400026)(1800799024); DIR:OUT; SFP:1101; X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Oct 2024 19:56:19.7867 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 74d8b1b0-6fdc-42e6-6ec2-08dcf78a979d 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: CO1PEPF000075EF.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: PH8PR12MB7421 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 refactors the power management library, addressing uncore power management. The primary changes involve the creation of dedicated directories for each driver within 'drivers/power/uncore/*'. The adjustment of meson.build files enables the selective activation of individual drivers. This refactor significantly improves code organization, enhances clarity and boosts maintainability. It lays the foundation for more focused development on individual drivers and facilitates seamless integration of future enhancements, particularly the AMD uncore driver. v10: - removed unused header inclusions - fixed rte_power_register_uncore_ops API description v9: - documentation update v8: - removed c++ guards for internal header files - renamed rte_power_uncore_ops.h for naming convention v7: - fixed build error with aarch32 gcc cross compilation v6: - fixed compilation error with symbol export in API v5: - fixed build errors for risc-v/ppc targets v4: - fixed build error with RTE_ASSERT Signed-off-by: Sivaprasad Tummala Acked-by: Huisong Li --- doc/guides/prog_guide/power_man.rst | 10 +- .../power/intel_uncore/intel_uncore.c | 18 +- .../power/intel_uncore/intel_uncore.h | 9 +- drivers/power/intel_uncore/meson.build | 6 + drivers/power/meson.build | 3 +- lib/power/meson.build | 2 +- lib/power/power_uncore_ops.h | 244 +++++++++++++++++ lib/power/rte_power_uncore.c | 259 +++++++++--------- lib/power/rte_power_uncore.h | 61 ++--- lib/power/version.map | 1 + 10 files changed, 440 insertions(+), 173 deletions(-) rename lib/power/power_intel_uncore.c => drivers/power/intel_uncore/intel_uncore.c (95%) rename lib/power/power_intel_uncore.h => drivers/power/intel_uncore/intel_uncore.h (97%) create mode 100644 drivers/power/intel_uncore/meson.build create mode 100644 lib/power/power_uncore_ops.h diff --git a/doc/guides/prog_guide/power_man.rst b/doc/guides/prog_guide/power_man.rst index f6674efe2d..1810ecf93b 100644 --- a/doc/guides/prog_guide/power_man.rst +++ b/doc/guides/prog_guide/power_man.rst @@ -191,8 +191,8 @@ API Overview for Ethernet PMD Power Management * **Set Scaling Max Freq**: Set the maximum frequency (kHz) to be used in Frequency Scaling mode. -Intel Uncore API ----------------- +Uncore API +---------- Abstract ~~~~~~~~ @@ -211,10 +211,10 @@ which was added in 5.6. This manipulates the context of MSR 0x620, which sets min/max of the uncore for the SKU. -API Overview for Intel Uncore -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Uncore API Overview +~~~~~~~~~~~~~~~~~~~ -Overview of each function in the Intel Uncore API, +Overview of each function in the Uncore API, with explanation of what they do. Each function should not be called in the fast path. diff --git a/lib/power/power_intel_uncore.c b/drivers/power/intel_uncore/intel_uncore.c similarity index 95% rename from lib/power/power_intel_uncore.c rename to drivers/power/intel_uncore/intel_uncore.c index 4eb9c5900a..804ad5d755 100644 --- a/lib/power/power_intel_uncore.c +++ b/drivers/power/intel_uncore/intel_uncore.c @@ -8,7 +8,7 @@ #include -#include "power_intel_uncore.h" +#include "intel_uncore.h" #include "power_common.h" #define MAX_NUMA_DIE 8 @@ -475,3 +475,19 @@ power_intel_uncore_get_num_dies(unsigned int pkg) return count; } + +static struct rte_power_uncore_ops intel_uncore_ops = { + .name = "intel-uncore", + .init = power_intel_uncore_init, + .exit = power_intel_uncore_exit, + .get_avail_freqs = power_intel_uncore_freqs, + .get_num_pkgs = power_intel_uncore_get_num_pkgs, + .get_num_dies = power_intel_uncore_get_num_dies, + .get_num_freqs = power_intel_uncore_get_num_freqs, + .get_freq = power_get_intel_uncore_freq, + .set_freq = power_set_intel_uncore_freq, + .freq_max = power_intel_uncore_freq_max, + .freq_min = power_intel_uncore_freq_min, +}; + +RTE_POWER_REGISTER_UNCORE_OPS(intel_uncore_ops); diff --git a/lib/power/power_intel_uncore.h b/drivers/power/intel_uncore/intel_uncore.h similarity index 97% rename from lib/power/power_intel_uncore.h rename to drivers/power/intel_uncore/intel_uncore.h index 20a3ba8ebe..b9343bd2ea 100644 --- a/lib/power/power_intel_uncore.h +++ b/drivers/power/intel_uncore/intel_uncore.h @@ -2,16 +2,15 @@ * Copyright(c) 2022 Intel Corporation */ -#ifndef POWER_INTEL_UNCORE_H -#define POWER_INTEL_UNCORE_H +#ifndef _INTEL_UNCORE_H +#define _INTEL_UNCORE_H /** * @file * RTE Intel Uncore Frequency Management */ -#include "rte_power.h" -#include "rte_power_uncore.h" +#include "power_uncore_ops.h" #ifdef __cplusplus extern "C" { @@ -223,4 +222,4 @@ power_intel_uncore_get_num_dies(unsigned int pkg); } #endif -#endif /* POWER_INTEL_UNCORE_H */ +#endif /* _INTEL_UNCORE_H */ diff --git a/drivers/power/intel_uncore/meson.build b/drivers/power/intel_uncore/meson.build new file mode 100644 index 0000000000..876df8ad14 --- /dev/null +++ b/drivers/power/intel_uncore/meson.build @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017 Intel Corporation +# Copyright(c) 2024 Advanced Micro Devices, Inc. + +sources = files('intel_uncore.c') +deps += ['power'] diff --git a/drivers/power/meson.build b/drivers/power/meson.build index 8c7215c639..c83047af94 100644 --- a/drivers/power/meson.build +++ b/drivers/power/meson.build @@ -6,7 +6,8 @@ drivers = [ 'amd_pstate', 'cppc', 'kvm_vm', - 'pstate' + 'pstate', + 'intel_uncore' ] std_deps = ['power'] diff --git a/lib/power/meson.build b/lib/power/meson.build index dd8e4393ac..5fa5d062e3 100644 --- a/lib/power/meson.build +++ b/lib/power/meson.build @@ -13,13 +13,13 @@ if not is_linux endif sources = files( 'power_common.c', - 'power_intel_uncore.c', 'rte_power.c', 'rte_power_uncore.c', 'rte_power_pmd_mgmt.c', ) headers = files( 'power_cpufreq.h', + 'power_uncore_ops.h', 'rte_power.h', 'rte_power_guest_channel.h', 'rte_power_pmd_mgmt.h', diff --git a/lib/power/power_uncore_ops.h b/lib/power/power_uncore_ops.h new file mode 100644 index 0000000000..eded2f7f1c --- /dev/null +++ b/lib/power/power_uncore_ops.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. + */ + +#ifndef _POWER_UNCORE_OPS_H +#define _POWER_UNCORE_OPS_H + +/** + * @file + * RTE Uncore Frequency Management + */ + +#include +#include + +#define RTE_POWER_UNCORE_DRIVER_NAMESZ 24 + +/** + * Initialize uncore frequency management for specific die on a package. + * It will get the available frequencies and prepare to set new die frequencies. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * - 0 on success. + * - Negative on error. + */ +typedef int (*rte_power_uncore_init_t)(unsigned int pkg, unsigned int die); + +/** + * Exit uncore frequency management on a specific die on a package. + * It will restore uncore min and* max values to previous values + * before initialization of API. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * - 0 on success. + * - Negative on error. + */ +typedef int (*rte_power_uncore_exit_t)(unsigned int pkg, unsigned int die); + +/** + * Return the current index of available frequencies of a specific die on a package. + * It should be protected outside of this function for threadsafe. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * The current index of available frequencies. + * If error, it will return 'RTE_POWER_INVALID_FREQ_INDEX = (~0)'. + */ +typedef uint32_t (*rte_power_get_uncore_freq_t)(unsigned int pkg, unsigned int die); + +/** + * Set minimum and maximum uncore frequency for specified die on a package + * to specified index value. + * It should be protected outside of this function for threadsafe. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * @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_uncore_freq_t)(unsigned int pkg, unsigned int die, uint32_t index); + +/** + * Return the list length of available frequencies in the index array. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * @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_uncore_freq_t)(unsigned int pkg, unsigned int die, uint32_t index); + +/** + * Return the list length of available frequencies in the index array. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * - The number of available index's in frequency array. + * - Negative on error. + */ +typedef int (*rte_power_uncore_get_num_freqs_t)(unsigned int pkg, unsigned int die); + +/** + * Return the list of available frequencies in the index array. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * @param freqs + * The buffer array to save the frequencies. + * @param num + * The number of frequencies to get. + * + * @return + * - The number of available index's in frequency array. + * - Negative on error. + */ +typedef int (*rte_power_uncore_freqs_t)(unsigned int pkg, unsigned int die, + uint32_t *freqs, uint32_t num); +/** + * Function pointers for generic frequency change functions. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * - 1 on success with frequency changed. + * - 0 on success without frequency changed. + * - Negative on error. + */ +typedef int (*rte_power_uncore_freq_change_t)(unsigned int pkg, unsigned int die); + +/** + * Return the number of packages (CPUs) on a system + * by parsing the uncore sysfs directory. + * + * This function should NOT be called in the fast path. + * + * @return + * - Zero on error. + * - Number of package on system on success. + */ +typedef unsigned int (*rte_power_uncore_get_num_pkgs_t)(void); + +/** + * Return the number of dies for pakckages (CPUs) specified + * from parsing the uncore sysfs directory. + * + * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * + * @return + * - Zero on error. + * - Number of dies for package on sucecss. + */ +typedef unsigned int (*rte_power_uncore_get_num_dies_t)(unsigned int pkg); +typedef void (*rte_power_uncore_driver_cb_t)(void); + +/** Structure defining uncore power operations structure */ +struct rte_power_uncore_ops { + RTE_TAILQ_ENTRY(rte_power_uncore_ops) next; /**< Next in list. */ + char name[RTE_POWER_UNCORE_DRIVER_NAMESZ]; /**< power mgmt driver. */ + rte_power_uncore_driver_cb_t cb; /**< Driver specific callbacks. */ + rte_power_uncore_init_t init; /**< Initialize power management. */ + rte_power_uncore_exit_t exit; /**< Exit power management. */ + rte_power_uncore_get_num_pkgs_t get_num_pkgs; + rte_power_uncore_get_num_dies_t get_num_dies; + rte_power_uncore_get_num_freqs_t get_num_freqs; /**< Number of available frequencies. */ + rte_power_uncore_freqs_t get_avail_freqs; /**< Get the available frequencies. */ + rte_power_get_uncore_freq_t get_freq; /**< Get frequency index. */ + rte_power_set_uncore_freq_t set_freq; /**< Set frequency index. */ + rte_power_uncore_freq_change_t freq_max; /**< Scale up frequency to highest. */ + rte_power_uncore_freq_change_t freq_min; /**< Scale up frequency to lowest. */ +}; + +/** + * Register power uncore frequency operations. + * @param ops + * Pointer to an ops structure to register. + * @return + * - 0: Success. + * - Negative on error. + */ +__rte_internal +int rte_power_register_uncore_ops(struct rte_power_uncore_ops *ops); + +/** + * Macro to statically register the ops of an uncore driver. + */ +#define RTE_POWER_REGISTER_UNCORE_OPS(ops) \ +RTE_INIT(power_hdlr_init_uncore_##ops) \ +{ \ + rte_power_register_uncore_ops(&ops); \ +} + +#endif /* _POWER_UNCORE_OPS_H */ diff --git a/lib/power/rte_power_uncore.c b/lib/power/rte_power_uncore.c index 48c75a5da0..741e067932 100644 --- a/lib/power/rte_power_uncore.c +++ b/lib/power/rte_power_uncore.c @@ -3,107 +3,58 @@ * Copyright(c) 2023 AMD Corporation */ -#include - -#include #include +#include -#include "power_common.h" #include "rte_power_uncore.h" -#include "power_intel_uncore.h" +#include "power_common.h" -enum rte_uncore_power_mgmt_env default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; +static enum rte_uncore_power_mgmt_env global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; +static struct rte_power_uncore_ops *global_uncore_ops; static rte_spinlock_t global_env_cfg_lock = RTE_SPINLOCK_INITIALIZER; +static RTE_TAILQ_HEAD(, rte_power_uncore_ops) uncore_ops_list = + TAILQ_HEAD_INITIALIZER(uncore_ops_list); -static uint32_t -power_get_dummy_uncore_freq(unsigned int pkg __rte_unused, - unsigned int die __rte_unused) -{ - return 0; -} - -static int -power_set_dummy_uncore_freq(unsigned int pkg __rte_unused, - unsigned int die __rte_unused, uint32_t index __rte_unused) -{ - return 0; -} - -static int -power_dummy_uncore_freq_max(unsigned int pkg __rte_unused, - unsigned int die __rte_unused) -{ - return 0; -} - -static int -power_dummy_uncore_freq_min(unsigned int pkg __rte_unused, - unsigned int die __rte_unused) -{ - return 0; -} +const char *uncore_env_str[] = { + "not set", + "auto-detect", + "intel-uncore", + "amd-hsmp" +}; -static int -power_dummy_uncore_freqs(unsigned int pkg __rte_unused, unsigned int die __rte_unused, - uint32_t *freqs __rte_unused, uint32_t num __rte_unused) +/* register the ops struct in rte_power_uncore_ops, return 0 on success. */ +int +rte_power_register_uncore_ops(struct rte_power_uncore_ops *driver_ops) { - return 0; -} + if (!driver_ops->init || !driver_ops->exit || !driver_ops->get_num_pkgs || + !driver_ops->get_num_dies || !driver_ops->get_num_freqs || + !driver_ops->get_avail_freqs || !driver_ops->get_freq || + !driver_ops->set_freq || !driver_ops->freq_max || + !driver_ops->freq_min) { + POWER_LOG(ERR, "Missing callbacks while registering power ops"); + return -1; + } -static int -power_dummy_uncore_get_num_freqs(unsigned int pkg __rte_unused, - unsigned int die __rte_unused) -{ - return 0; -} + if (driver_ops->cb) + driver_ops->cb(); -static unsigned int -power_dummy_uncore_get_num_pkgs(void) -{ - return 0; -} + TAILQ_INSERT_TAIL(&uncore_ops_list, driver_ops, next); -static unsigned int -power_dummy_uncore_get_num_dies(unsigned int pkg __rte_unused) -{ return 0; } -/* function pointers */ -rte_power_get_uncore_freq_t rte_power_get_uncore_freq = power_get_dummy_uncore_freq; -rte_power_set_uncore_freq_t rte_power_set_uncore_freq = power_set_dummy_uncore_freq; -rte_power_uncore_freq_change_t rte_power_uncore_freq_max = power_dummy_uncore_freq_max; -rte_power_uncore_freq_change_t rte_power_uncore_freq_min = power_dummy_uncore_freq_min; -rte_power_uncore_freqs_t rte_power_uncore_freqs = power_dummy_uncore_freqs; -rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs; -rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs; -rte_power_uncore_get_num_dies_t rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies; - -static void -reset_power_uncore_function_ptrs(void) -{ - rte_power_get_uncore_freq = power_get_dummy_uncore_freq; - rte_power_set_uncore_freq = power_set_dummy_uncore_freq; - rte_power_uncore_freq_max = power_dummy_uncore_freq_max; - rte_power_uncore_freq_min = power_dummy_uncore_freq_min; - rte_power_uncore_freqs = power_dummy_uncore_freqs; - rte_power_uncore_get_num_freqs = power_dummy_uncore_get_num_freqs; - rte_power_uncore_get_num_pkgs = power_dummy_uncore_get_num_pkgs; - rte_power_uncore_get_num_dies = power_dummy_uncore_get_num_dies; -} - int rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env) { - int ret; + int ret = -1; + struct rte_power_uncore_ops *ops; rte_spinlock_lock(&global_env_cfg_lock); - if (default_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) { + if (global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) { POWER_LOG(ERR, "Uncore Power Management Env already set."); - rte_spinlock_unlock(&global_env_cfg_lock); - return -1; + goto out; } if (env == RTE_UNCORE_PM_ENV_AUTO_DETECT) @@ -113,23 +64,20 @@ rte_power_set_uncore_env(enum rte_uncore_power_mgmt_env env) */ env = RTE_UNCORE_PM_ENV_INTEL_UNCORE; - ret = 0; - if (env == RTE_UNCORE_PM_ENV_INTEL_UNCORE) { - rte_power_get_uncore_freq = power_get_intel_uncore_freq; - rte_power_set_uncore_freq = power_set_intel_uncore_freq; - rte_power_uncore_freq_min = power_intel_uncore_freq_min; - rte_power_uncore_freq_max = power_intel_uncore_freq_max; - rte_power_uncore_freqs = power_intel_uncore_freqs; - rte_power_uncore_get_num_freqs = power_intel_uncore_get_num_freqs; - rte_power_uncore_get_num_pkgs = power_intel_uncore_get_num_pkgs; - rte_power_uncore_get_num_dies = power_intel_uncore_get_num_dies; - } else { - POWER_LOG(ERR, "Invalid Power Management Environment(%d) set", env); - ret = -1; - goto out; - } + if (env <= RTE_DIM(uncore_env_str)) { + RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next) + if (strncmp(ops->name, uncore_env_str[env], + RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) { + global_uncore_env = env; + global_uncore_ops = ops; + ret = 0; + goto out; + } + POWER_LOG(ERR, "Power Management (%s) not supported", + uncore_env_str[env]); + } else + POWER_LOG(ERR, "Invalid Power Management Environment"); - default_uncore_env = env; out: rte_spinlock_unlock(&global_env_cfg_lock); return ret; @@ -139,43 +87,43 @@ void rte_power_unset_uncore_env(void) { rte_spinlock_lock(&global_env_cfg_lock); - default_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; - reset_power_uncore_function_ptrs(); + global_uncore_env = RTE_UNCORE_PM_ENV_NOT_SET; rte_spinlock_unlock(&global_env_cfg_lock); } enum rte_uncore_power_mgmt_env rte_power_get_uncore_env(void) { - return default_uncore_env; + return global_uncore_env; } int rte_power_uncore_init(unsigned int pkg, unsigned int die) { int ret = -1; - - switch (default_uncore_env) { - case RTE_UNCORE_PM_ENV_INTEL_UNCORE: - return power_intel_uncore_init(pkg, die); - default: - POWER_LOG(INFO, "Uncore Env isn't set yet!"); - break; - } - - /* Auto detect Environment */ - POWER_LOG(INFO, "Attempting to initialise Intel Uncore power mgmt..."); - ret = power_intel_uncore_init(pkg, die); - if (ret == 0) { - rte_power_set_uncore_env(RTE_UNCORE_PM_ENV_INTEL_UNCORE); - goto out; - } - - if (default_uncore_env == RTE_UNCORE_PM_ENV_NOT_SET) { - POWER_LOG(ERR, "Unable to set Power Management Environment " - "for package %u Die %u", pkg, die); - ret = 0; - } + struct rte_power_uncore_ops *ops; + uint8_t env; + + if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) && + (global_uncore_env != RTE_UNCORE_PM_ENV_AUTO_DETECT)) + return global_uncore_ops->init(pkg, die); + + /* Auto Detect Environment */ + RTE_TAILQ_FOREACH(ops, &uncore_ops_list, next) + if (ops) { + POWER_LOG(INFO, + "Attempting to initialise %s power management...", + ops->name); + ret = ops->init(pkg, die); + if (ret == 0) { + for (env = 0; env < RTE_DIM(uncore_env_str); env++) + if (strncmp(ops->name, uncore_env_str[env], + RTE_POWER_UNCORE_DRIVER_NAMESZ) == 0) { + rte_power_set_uncore_env(env); + goto out; + } + } + } out: return ret; } @@ -183,12 +131,69 @@ rte_power_uncore_init(unsigned int pkg, unsigned int die) int rte_power_uncore_exit(unsigned int pkg, unsigned int die) { - switch (default_uncore_env) { - case RTE_UNCORE_PM_ENV_INTEL_UNCORE: - return power_intel_uncore_exit(pkg, die); - default: - POWER_LOG(ERR, "Uncore Env has not been set, unable to exit gracefully"); - break; - } + if ((global_uncore_env != RTE_UNCORE_PM_ENV_NOT_SET) && + global_uncore_ops) + return global_uncore_ops->exit(pkg, die); + + POWER_LOG(ERR, + "Uncore Env has not been set, unable to exit gracefully"); + return -1; } + +uint32_t +rte_power_get_uncore_freq(unsigned int pkg, unsigned int die) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->get_freq(pkg, die); +} + +int +rte_power_set_uncore_freq(unsigned int pkg, unsigned int die, uint32_t index) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->set_freq(pkg, die, index); +} + +int +rte_power_uncore_freq_max(unsigned int pkg, unsigned int die) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->freq_max(pkg, die); +} + +int +rte_power_uncore_freq_min(unsigned int pkg, unsigned int die) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->freq_min(pkg, die); +} + +int +rte_power_uncore_freqs(unsigned int pkg, unsigned int die, + uint32_t *freqs, uint32_t num) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->get_avail_freqs(pkg, die, freqs, num); +} + +int +rte_power_uncore_get_num_freqs(unsigned int pkg, unsigned int die) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->get_num_freqs(pkg, die); +} + +unsigned int +rte_power_uncore_get_num_pkgs(void) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->get_num_pkgs(); +} + +unsigned int +rte_power_uncore_get_num_dies(unsigned int pkg) +{ + RTE_ASSERT(global_uncore_ops != NULL); + return global_uncore_ops->get_num_dies(pkg); +} diff --git a/lib/power/rte_power_uncore.h b/lib/power/rte_power_uncore.h index 99859042dd..67d55cbf96 100644 --- a/lib/power/rte_power_uncore.h +++ b/lib/power/rte_power_uncore.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2022 Intel Corporation - * Copyright(c) 2023 AMD Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. */ #ifndef RTE_POWER_UNCORE_H @@ -11,8 +11,7 @@ * RTE Uncore Frequency Management */ -#include -#include "rte_power.h" +#include "power_uncore_ops.h" #ifdef __cplusplus extern "C" { @@ -116,9 +115,7 @@ rte_power_uncore_exit(unsigned int pkg, unsigned int die); * The current index of available frequencies. * If error, it will return 'RTE_POWER_INVALID_FREQ_INDEX = (~0)'. */ -typedef uint32_t (*rte_power_get_uncore_freq_t)(unsigned int pkg, unsigned int die); - -extern rte_power_get_uncore_freq_t rte_power_get_uncore_freq; +uint32_t rte_power_get_uncore_freq(unsigned int pkg, unsigned int die); /** * Set minimum and maximum uncore frequency for specified die on a package @@ -141,12 +138,14 @@ extern rte_power_get_uncore_freq_t rte_power_get_uncore_freq; * - 0 on success without frequency changed. * - Negative on error. */ -typedef int (*rte_power_set_uncore_freq_t)(unsigned int pkg, unsigned int die, uint32_t index); - -extern rte_power_set_uncore_freq_t rte_power_set_uncore_freq; +int rte_power_set_uncore_freq(unsigned int pkg, unsigned int die, uint32_t index); /** - * Function pointer definition for generic frequency change functions. + * Set minimum and maximum uncore frequency for specified die on a package + * to maximum value according to the available frequencies. + * It should be protected outside of this function for threadsafe. + * + * This function should NOT be called in the fast path. * * @param pkg * Package number. @@ -160,16 +159,7 @@ extern rte_power_set_uncore_freq_t rte_power_set_uncore_freq; * - 0 on success without frequency changed. * - Negative on error. */ -typedef int (*rte_power_uncore_freq_change_t)(unsigned int pkg, unsigned int die); - -/** - * Set minimum and maximum uncore frequency for specified die on a package - * to maximum value according to the available frequencies. - * It should be protected outside of this function for threadsafe. - * - * This function should NOT be called in the fast path. - */ -extern rte_power_uncore_freq_change_t rte_power_uncore_freq_max; +int rte_power_uncore_freq_max(unsigned int pkg, unsigned int die); /** * Set minimum and maximum uncore frequency for specified die on a package @@ -177,8 +167,20 @@ extern rte_power_uncore_freq_change_t rte_power_uncore_freq_max; * It should be protected outside of this function for threadsafe. * * This function should NOT be called in the fast path. + * + * @param pkg + * Package number. + * Each physical CPU in a system is referred to as a package. + * @param die + * Die number. + * Each package can have several dies connected together via the uncore mesh. + * + * @return + * - 1 on success with frequency changed. + * - 0 on success without frequency changed. + * - Negative on error. */ -extern rte_power_uncore_freq_change_t rte_power_uncore_freq_min; +int rte_power_uncore_freq_min(unsigned int pkg, unsigned int die); /** * Return the list of available frequencies in the index array. @@ -200,11 +202,10 @@ extern rte_power_uncore_freq_change_t rte_power_uncore_freq_min; * - The number of available index's in frequency array. * - Negative on error. */ -typedef int (*rte_power_uncore_freqs_t)(unsigned int pkg, unsigned int die, +__rte_experimental +int rte_power_uncore_freqs(unsigned int pkg, unsigned int die, uint32_t *freqs, uint32_t num); -extern rte_power_uncore_freqs_t rte_power_uncore_freqs; - /** * Return the list length of available frequencies in the index array. * @@ -221,9 +222,7 @@ extern rte_power_uncore_freqs_t rte_power_uncore_freqs; * - The number of available index's in frequency array. * - Negative on error. */ -typedef int (*rte_power_uncore_get_num_freqs_t)(unsigned int pkg, unsigned int die); - -extern rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs; +int rte_power_uncore_get_num_freqs(unsigned int pkg, unsigned int die); /** * Return the number of packages (CPUs) on a system @@ -235,9 +234,7 @@ extern rte_power_uncore_get_num_freqs_t rte_power_uncore_get_num_freqs; * - Zero on error. * - Number of package on system on success. */ -typedef unsigned int (*rte_power_uncore_get_num_pkgs_t)(void); - -extern rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs; +unsigned int rte_power_uncore_get_num_pkgs(void); /** * Return the number of dies for pakckages (CPUs) specified @@ -253,9 +250,7 @@ extern rte_power_uncore_get_num_pkgs_t rte_power_uncore_get_num_pkgs; * - Zero on error. * - Number of dies for package on sucecss. */ -typedef unsigned int (*rte_power_uncore_get_num_dies_t)(unsigned int pkg); - -extern rte_power_uncore_get_num_dies_t rte_power_uncore_get_num_dies; +unsigned int rte_power_uncore_get_num_dies(unsigned int pkg); #ifdef __cplusplus } diff --git a/lib/power/version.map b/lib/power/version.map index 9c1ed4d9d6..f442329bbc 100644 --- a/lib/power/version.map +++ b/lib/power/version.map @@ -57,6 +57,7 @@ INTERNAL { global: rte_power_register_cpufreq_ops; + rte_power_register_uncore_ops; rte_power_logtype; cpufreq_check_scaling_driver; power_get_lcore_mapped_cpu_id; -- 2.34.1