[PATCH v5 2/4] lib/amdgpu: Add AMD platform filtering backend
<[email protected]> Wed, 5 Aug 2026 16:28:46 -0400
| Newsgroups | org.freedesktop.lists.igt-dev |
|---|---|
| Message-ID | <[email protected]> |
From: Vitaly Prosyak <[email protected]> Implement the AMD-specific backend for the generic platform filtering framework, providing: - ASIC identification via amdgpu family_id and chip_rev ranges - ASIC name table mapping (navi10, navi48, arcturus, etc.) - AMD-specific built-in skip rules - amd_platform_filter_init() convenience function for AMD tests This is a pluggable backend accessed through platform_filter_ops callbacks. The core framework has zero AMD-specific knowledge. To add support for another vendor (e.g., Intel): 1. Create lib/i915/intel_platform.c/h 2. Implement platform_filter_ops callbacks 3. Define Intel platform data (platform_id, stepping ranges) 4. Call intel_platform_filter_init() from Intel tests Usage in AMD tests: amd_platform_filter_init(&gpu_info); igt_platform_require(igt_test_name(), my-subtest); Example skip via environment variable: export IGT_PLATFORM_SKIP_CONFIG=navi48:amd_basic:*-UMQ:unstable v3 changes: - This is now patch 2/6 (was 3/7 in v2) due to squashing of patches 1+2 per Kamil Konieczny's review feedback - No code changes from v2 v2: Address review feedback from Kamil Konieczny: - Fixed compilation error: removed extra */ on line 9 - Added missing #include <stddef.h> to fix size_t errors - Added kernel-doc to amd_platform_filter_init() - Verified bisect-safety Cc: Kamil Konieczny <[email protected]> Cc: Jani Nikula <[email protected]> Cc: Krzysztof Karas <[email protected]> Cc: Jesse Zhang <[email protected]> Cc: Christian König <[email protected]> Cc: Alex Deucher <[email protected]> Signed-off-by: Vitaly Prosyak <[email protected]> Reviewed-by: Jesse Zhang <[email protected]> Change-Id: I578444cd7b3b4d821cf1f3502cd61ea4cae946e3 --- lib/amdgpu/amd_platform.c | 328 ++++++++++++++++++++++++++++++++++++++ lib/amdgpu/amd_platform.h | 53 ++++++ lib/meson.build | 1 + 3 files changed, 382 insertions(+) create mode 100644 lib/amdgpu/amd_platform.c create mode 100644 lib/amdgpu/amd_platform.h diff --git a/lib/amdgpu/amd_platform.c b/lib/amdgpu/amd_platform.c new file mode 100644 index 000000000..1c6a72a49 --- /dev/null +++ b/lib/amdgpu/amd_platform.c @@ -0,0 +1,328 @@ +// SPDX-License-Identifier: MIT +// Copyright 2026 Advanced Micro Devices, Inc. +/* + * AMD-specific platform filtering backend + * + * Implements platform_filter_ops callbacks for AMD GPUs, providing + * platform identification and matching logic based on ASIC family/chip. + */ + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> + +#include "igt.h" +#include "igt_platform_filter.h" +#include "amd_platform.h" +#include "amdgpu_asic_addr.h" + +/** + * AMD platform data structures + * + * These structures define how AMD ASICs are matched for filtering. + * They use family/chip ranges similar to amd_queue_reset.c + */ + +/* Maximum ASIC family ranges per skip entry */ +#define MAX_ASIC_RANGES 4 + +/** + * struct amd_asic_range - ASIC family range for matching + * + * Similar to struct used in amd_queue_reset.c for defining ASIC ranges. + * Uses definitions from amdgpu_asic_addr.h + */ +struct amd_asic_range { + int family_id; /* FAMILY_NV, FAMILY_GFX1200, etc. */ + int chip_id_min; /* Min chip revision */ + int chip_id_max; /* Max chip revision */ +}; + +/** + * struct amd_platform_data - AMD platform matching data + * + * This is stored in platform_skip_entry->platform_data field. + * Contains array of ASIC ranges to match against. + */ +struct amd_platform_data { + struct amd_asic_range ranges[MAX_ASIC_RANGES]; + int num_ranges; +}; + +/* ASIC name to family/chip mapping table */ +struct asic_info { + const char *name; + int family_id; + int chip_id_min; + int chip_id_max; +}; + +static const struct asic_info asic_table[] = { + /* GFX12 - using ranges from amdgpu_asic_addr.h */ + { "navi48", FAMILY_GFX1200, AMDGPU_GFX1200_RANGE }, + { "navi44", FAMILY_GFX1200, AMDGPU_GFX1200_RANGE }, + + /* GFX11.5 */ + { "gfx1150", FAMILY_GFX1150, AMDGPU_GFX1150_RANGE }, + { "gfx1151", FAMILY_GFX1150, AMDGPU_GFX1151_RANGE }, + { "gfx1152", FAMILY_GFX1150, AMDGPU_GFX1152_RANGE }, + { "gfx1153", FAMILY_GFX1150, AMDGPU_GFX1153_RANGE }, + + /* GFX11 */ + { "gfx1100", FAMILY_GFX1100, AMDGPU_GFX1100_RANGE }, + { "gfx1101", FAMILY_GFX1100, AMDGPU_GFX1101_RANGE }, + { "gfx1102", FAMILY_GFX1100, AMDGPU_GFX1102_RANGE }, + { "gfx1103_r1", FAMILY_GFX1103, AMDGPU_GFX1103_R1_RANGE }, + { "gfx1103_r2", FAMILY_GFX1103, AMDGPU_GFX1103_R2_RANGE }, + { "navi31", FAMILY_GFX1100, AMDGPU_GFX1100_RANGE }, + { "navi32", FAMILY_GFX1100, AMDGPU_GFX1101_RANGE }, + { "navi33", FAMILY_GFX1100, AMDGPU_GFX1102_RANGE }, + + /* GFX10.3 */ + { "sienna_cichlid", FAMILY_NV, AMDGPU_SIENNA_CICHLID_RANGE }, + { "navy_flounder", FAMILY_NV, AMDGPU_NAVY_FLOUNDER_RANGE }, + { "dimgrey_cavefish", FAMILY_NV, AMDGPU_DIMGREY_CAVEFISH_RANGE }, + { "beige_goby", FAMILY_NV, AMDGPU_BEIGE_GOBY_RANGE }, + { "yellow_carp", FAMILY_YC, AMDGPU_YELLOW_CARP_RANGE }, + { "vangogh", FAMILY_VGH, AMDGPU_VANGOGH_RANGE }, + + /* GFX10 */ + { "navi10", FAMILY_NV, AMDGPU_NAVI10_RANGE }, + { "navi12", FAMILY_NV, AMDGPU_NAVI12_RANGE }, + { "navi14", FAMILY_NV, AMDGPU_NAVI14_RANGE }, + { "navi21", FAMILY_NV, AMDGPU_SIENNA_CICHLID_RANGE }, + { "navi22", FAMILY_NV, AMDGPU_NAVY_FLOUNDER_RANGE }, + { "navi23", FAMILY_NV, AMDGPU_DIMGREY_CAVEFISH_RANGE }, + { "navi24", FAMILY_NV, AMDGPU_BEIGE_GOBY_RANGE }, + + /* CDNA */ + { "arcturus", FAMILY_AI, AMDGPU_ARCTURUS_RANGE }, + { "aldebaran", FAMILY_AI, AMDGPU_ALDEBARAN_RANGE }, + + /* GFX9 */ + { "vega10", FAMILY_AI, AMDGPU_VEGA10_RANGE }, + { "vega12", FAMILY_AI, AMDGPU_VEGA12_RANGE }, + { "vega20", FAMILY_AI, AMDGPU_VEGA20_RANGE }, + { "raven", FAMILY_RV, AMDGPU_RAVEN_RANGE }, + { "raven2", FAMILY_RV, AMDGPU_RAVEN2_RANGE }, + { "renoir", FAMILY_RV, AMDGPU_RENOIR_RANGE }, + + /* GFX8 (VI/Polaris) */ + { "polaris10", FAMILY_VI, AMDGPU_POLARIS10_RANGE }, + { "polaris11", FAMILY_VI, AMDGPU_POLARIS11_RANGE }, + { "polaris12", FAMILY_VI, AMDGPU_POLARIS12_RANGE }, + { "fiji", FAMILY_VI, AMDGPU_FIJI_RANGE }, + { "tonga", FAMILY_VI, AMDGPU_TONGA_RANGE }, + { "iceland", FAMILY_VI, AMDGPU_ICELAND_RANGE }, + { "carrizo", FAMILY_CZ, AMDGPU_CARRIZO_RANGE }, + { "stoney", FAMILY_CZ, AMDGPU_STONEY_RANGE }, + + { NULL, 0, 0, 0 } +}; + +/* Helper: Get ASIC info by name (case-insensitive) */ +static const struct asic_info *get_asic_info(const char *name) +{ + const struct asic_info *info; + + if (!name) + return NULL; + + for (info = asic_table; info->name; info++) { + if (strcasecmp(info->name, name) == 0) + return info; + } + return NULL; +} + +/* Helper: Get ASIC name by family/chip */ +static const char *get_asic_name(int family_id, int chip_rev) +{ + const struct asic_info *info; + + for (info = asic_table; info->name; info++) { + if (info->family_id == family_id && + chip_rev >= info->chip_id_min && + chip_rev < info->chip_id_max) + return info->name; + } + return "unknown"; +} + +/* ================================================================ + * AMD PLATFORM FILTER OPS IMPLEMENTATION + * ================================================================ */ + +static const char *amd_get_platform_name(const void *platform_info) +{ + const struct amdgpu_gpu_info *gpu_info = platform_info; + + if (!gpu_info) + return "unknown"; + + return get_asic_name(gpu_info->family_id, gpu_info->chip_rev); +} + +static bool amd_match_platform(const void *platform_info, const void *platform_data) +{ + const struct amdgpu_gpu_info *gpu_info = platform_info; + const struct amd_platform_data *amd_data = platform_data; + int i; + + if (!gpu_info || !amd_data) + return false; + + /* If no ranges specified, match all platforms */ + if (amd_data->num_ranges == 0) + return true; + + /* Check if GPU matches any of the ASIC ranges */ + for (i = 0; i < amd_data->num_ranges && i < MAX_ASIC_RANGES; i++) { + if (amd_data->ranges[i].family_id == gpu_info->family_id) { + int chip_rev = gpu_info->chip_rev; + if (chip_rev >= amd_data->ranges[i].chip_id_min && + chip_rev < amd_data->ranges[i].chip_id_max) { + return true; + } + } + } + + return false; +} + +static bool amd_parse_platform_config(const char *platform_str, void **platform_data_out) +{ + const struct asic_info *info; + struct amd_platform_data *amd_data; + + info = get_asic_info(platform_str); + if (!info) { + igt_warn("Unknown AMD ASIC name: %s\n", platform_str); + return false; + } + + amd_data = malloc(sizeof(*amd_data)); + if (!amd_data) + return false; + + memset(amd_data, 0, sizeof(*amd_data)); + amd_data->ranges[0].family_id = info->family_id; + amd_data->ranges[0].chip_id_min = info->chip_id_min; + amd_data->ranges[0].chip_id_max = info->chip_id_max; + amd_data->num_ranges = 1; + + *platform_data_out = amd_data; + return true; +} + +static void amd_dump_platform_data(const void *platform_data) +{ + const struct amd_platform_data *amd_data = platform_data; + int i; + + if (!amd_data) { + printf("(all platforms)"); + return; + } + + for (i = 0; i < amd_data->num_ranges && i < MAX_ASIC_RANGES; i++) { + if (i > 0) + printf(", "); + printf("{0x%02X, 0x%02X-0x%02X}", + amd_data->ranges[i].family_id, + amd_data->ranges[i].chip_id_min, + amd_data->ranges[i].chip_id_max); + } +} + +/* ================================================================ + * AMD BUILT-IN SKIP RULES + * ================================================================ + * + * These are production skip rules. They are checked FIRST before + * config file or environment variable. + * + * To add a skip rule: + * 1. Define platform data with ASIC ranges + * 2. Add entry to builtin_skip_table[] + * 3. Rebuild IGT + * + * Example formats (uncomment to use): + * + * Single ASIC: + * static struct amd_platform_data navi44_data = { + * .ranges = { {FAMILY_GFX1200, AMDGPU_GFX1200_RANGE} }, + * .num_ranges = 1 + * }; + * { "amd_basic", "*-UMQ", "UMQ not supported on Navi44", &navi44_data }, + * + * Multiple ASICs: + * static struct amd_platform_data navi10_12_14_data = { + * .ranges = { + * {FAMILY_NV, AMDGPU_NAVI10_RANGE}, + * {FAMILY_NV, AMDGPU_NAVI12_RANGE}, + * {FAMILY_NV, AMDGPU_NAVI14_RANGE} + * }, + * .num_ranges = 3 + * }; + * { "amd_userq_abort", "*", "Queue reset unstable", &navi10_12_14_data }, + * + * All platforms (no platform restriction): + * { "test_name", "subtest", "reason", NULL }, + */ + +static const struct platform_skip_entry builtin_skip_table[] = { + /* Add production skip rules here */ + + /* Sentinel */ + {} +}; + +static const struct platform_skip_entry *amd_get_builtin_rules(int *count_out) +{ + int count = 0; + + /* Count entries (stop at sentinel) */ + while (builtin_skip_table[count].test_name || + builtin_skip_table[count].subtest_glob || + builtin_skip_table[count].reason) + count++; + + *count_out = count; + return builtin_skip_table; +} + +/* AMD platform filter operations */ +static const struct platform_filter_ops amd_platform_ops = { + .name = "amd", + .get_platform_name = amd_get_platform_name, + .match_platform = amd_match_platform, + .parse_platform_config = amd_parse_platform_config, + .get_builtin_rules = amd_get_builtin_rules, + .dump_platform_data = amd_dump_platform_data, +}; + +/* ================================================================ + * PUBLIC API + * ================================================================ */ + +const struct platform_filter_ops *amd_platform_get_ops(void) +{ + return &amd_platform_ops; +} + +/** + * amd_platform_filter_init: + * @gpu_info: AMD GPU information from amdgpu query + * + * Initialize platform filtering for AMD GPUs. This is a convenience + * wrapper that sets up the generic filtering framework with AMD-specific + * callbacks and GPU identification data. + * + * Must be called before using igt_platform_require() in AMD tests. + */ +void amd_platform_filter_init(const struct amdgpu_gpu_info *gpu_info) +{ + igt_platform_filter_init(&amd_platform_ops, gpu_info); +} diff --git a/lib/amdgpu/amd_platform.h b/lib/amdgpu/amd_platform.h new file mode 100644 index 000000000..fd233a053 --- /dev/null +++ b/lib/amdgpu/amd_platform.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: MIT + * Copyright 2026 Advanced Micro Devices, Inc. + */ + +#ifndef AMD_PLATFORM_H +#define AMD_PLATFORM_H + +#include "igt_platform_filter.h" +#include "amd_ip_blocks.h" + +/** + * SECTION: amd_platform + * @short_description: AMD-specific platform filtering backend + * @title: AMD Platform + * @include: amd_platform.h + * + * AMD implementation of platform filtering that plugs into the generic + * IGT platform filter framework. + * + * This backend provides: + * - ASIC identification and matching based on family/chip ranges + * - Built-in skip rules for AMD GPUs + * - Integration with amdgpu_asic_addr.h definitions + * + * Usage in AMD tests: + * igt_fixture() { + * setup_amdgpu_ip_blocks(...); + * amd_platform_filter_init(&gpu_info); + * } + * + * igt_subtest("my-test") { + * // Automatic filtering - no manual call needed! + * test_code(); + * } + */ + +/** + * amd_platform_filter_init - Initialize AMD platform filtering + * @gpu_info: AMDGPU GPU information structure + * + * Convenience wrapper that initializes the generic platform filter + * with AMD-specific operations and GPU info. + */ +void amd_platform_filter_init(const struct amdgpu_gpu_info *gpu_info); + +/** + * amd_platform_get_ops - Get AMD platform filter operations + * + * Returns: AMD platform_filter_ops structure + */ +const struct platform_filter_ops *amd_platform_get_ops(void); + +#endif /* AMD_PLATFORM_H */ diff --git a/lib/meson.build b/lib/meson.build index 1c04ee813..47b69da19 100644 --- a/lib/meson.build +++ b/lib/meson.build @@ -181,6 +181,7 @@ if libdrm_amdgpu.found() lib_deps += libdrm_amdgpu lib_sources += [ 'amdgpu/amd_memory.c', + 'amdgpu/amd_platform.c', 'amdgpu/amd_command_submission.c', 'amdgpu/amd_compute.c', 'amdgpu/amd_cs_radv.c', -- 2.43.0