git: 8aab12ca1898 - main - amdsmu: Fix CPU-model-specific matching

From: Olivier Certner <olce_at_FreeBSD.org>
Date: Fri, 18 Sep 2026 13:26:18 UTC
The branch main has been updated by olce:

URL: https://cgit.FreeBSD.org/src/commit/?id=8aab12ca1898e3fe62a85c39aa1921950d739284

commit 8aab12ca1898e3fe62a85c39aa1921950d739284
Author:     Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2026-09-17 13:38:57 +0000
Commit:     Olivier Certner <olce@FreeBSD.org>
CommitDate: 2026-09-18 13:25:59 +0000

    amdsmu: Fix CPU-model-specific matching
    
    For Krackan Point, CPU-model-specific matching would not work because
    amdsmu_match() browses amdsmu_products[] in order and returns the first
    match, and the Krackan Point's 'struct amdsmu_product' object variant
    with a 'model' field of 0, indicating that any model matches, is listed
    before the variant with model 0x70 in amdsmu_products[].
    
    In practice, this means that reporting of IP blocks for Krackan Point
    model 0x70 only was broken.  Specifically, not all the existing blocks
    were reported and most statistics were not attributed to the right
    blocks.
    
    Fix this by making amdsmu_match() parse amdsmu_products[] in reverse, so
    CPU-model-generic entries can continue to appear first and new specific
    ones can be added after them, which is the expected chronological order
    of additions.
    
    While here, since the CPU model is between 0 and 255, change the type
    used for CPU models to an 'int' and use the special value -1 to skip
    model match, as there exist CPUs reporting 0 as the model (even if, to
    our knowledge, only old CPUs seem to be doing that).
    
    While here, fix alignement and whitespace in amdsmu_products[]'s
    initializers.
    
    Reviewed by:    obiwac
    Fixes:          9c77fb6aaa36 ("amdsmu: Add Krackan Point support")
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D59788
---
 sys/dev/amdsmu/amdsmu.c | 20 ++++++++------------
 sys/dev/amdsmu/amdsmu.h | 27 ++++++++++++++++-----------
 2 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
index f7edc073efea..45e5cf7e944d 100644
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -30,21 +30,17 @@ amdsmu_match(device_t dev, const struct amdsmu_product **product_out)
 	const uint16_t vendorid = pci_get_vendor(dev);
 	const uint16_t deviceid = pci_get_device(dev);
 
-	const uint32_t model = CPUID_TO_MODEL(cpu_id);
+	/* CPUID_TO_MODEL() returns a number between 0 and 255. */
+	const int model = CPUID_TO_MODEL(cpu_id);
 
-	for (size_t i = 0; i < nitems(amdsmu_products); i++) {
-		const struct amdsmu_product *prod = &amdsmu_products[i];
+	/* Reverse order to match specific models first. */
+	for (size_t i = nitems(amdsmu_products); i != 0; i--) {
+		const struct amdsmu_product *prod = &amdsmu_products[i-1];
 
 		if (vendorid == prod->amdsmu_vendorid &&
-		    deviceid == prod->amdsmu_deviceid) {
-
-			/*
-			 * Some Krackan Point devices have different ip blocks
-			 * based on CPU model.
-			 */
-			if (prod->model != 0x00 && model != prod->model)
-				continue;
-
+		    deviceid == prod->amdsmu_deviceid &&
+		    /* -1 indicates all models match. */
+		    (prod->model == -1 || model == prod->model)) {
 			if (product_out != NULL)
 				*product_out = prod;
 			return (true);
diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h
index ede275ac7168..2dc3890afb93 100644
--- a/sys/dev/amdsmu/amdsmu.h
+++ b/sys/dev/amdsmu/amdsmu.h
@@ -87,26 +87,31 @@ CTASSERT(nitems(amdsmu_ip_blocks_names_v2) <= IP_MAX_BLOCK_NAMES);
 static const struct amdsmu_product {
 	uint16_t	amdsmu_vendorid;
 	uint16_t	amdsmu_deviceid;
-	uint32_t	model;
+	/* CPU model from CPUID_TO_MODEL() if specific to that model, or -1. */
+	int		model;
 	int16_t		idlemask_reg;
 	size_t		ip_block_count;
 	const char 	**ip_blocks_names;
 	uint32_t	amdsmu_msg;
 } amdsmu_products[] = {
-	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_CEZANNE_ROOT, 0x00,
-	    SMU_REG_IDLEMASK_CEZANNE,	12 , amdsmu_ip_blocks_names,
+	/*
+	 * Lines with -1 as 'model' must come before ones having same vendor and
+	 * device IDs but a real CPU model.
+	 */
+	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_CEZANNE_ROOT,		-1,
+	    SMU_REG_IDLEMASK_CEZANNE,	12,	amdsmu_ip_blocks_names,
 	    SMU_REG_MSG_CEZANNE},
-	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_REMBRANDT_ROOT, 0x00,
-	    SMU_REG_IDLEMASK_PHOENIX,	12 , amdsmu_ip_blocks_names,
+	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_REMBRANDT_ROOT,	-1,
+	    SMU_REG_IDLEMASK_PHOENIX,	12,	amdsmu_ip_blocks_names,
 	    SMU_REG_MSG_CEZANNE},
-	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_PHOENIX_ROOT, 0x00,
-	    SMU_REG_IDLEMASK_PHOENIX,	21 , amdsmu_ip_blocks_names,
+	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_PHOENIX_ROOT,		-1,
+	    SMU_REG_IDLEMASK_PHOENIX,	21,	amdsmu_ip_blocks_names,
 	    SMU_REG_MSG_CEZANNE},
-	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x00,
-	    SMU_REG_IDLEMASK_KRACKAN,	22, amdsmu_ip_blocks_names,
+	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT,	-1,
+	    SMU_REG_IDLEMASK_KRACKAN,	22,	amdsmu_ip_blocks_names,
 	    SMU_REG_MSG_KRACKAN },
-	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT, 0x70,
-	    SMU_REG_IDLEMASK_KRACKAN,	25, amdsmu_ip_blocks_names_v2,
+	{ CPU_VENDOR_AMD,	PCI_DEVICEID_AMD_KRACKAN_POINT_ROOT,	0x70,
+	    SMU_REG_IDLEMASK_KRACKAN,	25,	amdsmu_ip_blocks_names_v2,
 	    SMU_REG_MSG_KRACKAN },
 	/*
 	 * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support