Skip to content

Commit 51c33f3

Browse files
superm1joergroedel
authored andcommitted
iommu/amd: Allow matching ACPI HID devices without matching UIDs
A BIOS upgrade has changed the IVRS DTE UID for a device that no longer matches the UID in the SSDT. In this case there is only one ACPI device on the system with that _HID but the _UID mismatch. IVRS: ``` Subtable Type : F0 [Device Entry: ACPI HID Named Device] Device ID : 0060 Data Setting (decoded below) : 40 INITPass : 0 EIntPass : 0 NMIPass : 0 Reserved : 0 System MGMT : 0 LINT0 Pass : 1 LINT1 Pass : 0 ACPI HID : "MSFT0201" ACPI CID : 0000000000000000 UID Format : 02 UID Length : 09 UID : "\_SB.MHSP" ``` SSDT: ``` Device (MHSP) { Name (_ADR, Zero) // _ADR: Address Name (_HID, "MSFT0201") // _HID: Hardware ID Name (_UID, One) // _UID: Unique ID ``` To handle this case; while enumerating ACPI devices in get_acpihid_device_id() count the number of matching ACPI devices with a matching _HID. If there is exactly one _HID match then accept it even if the UID doesn't match. Other operating systems allow this, but the current IVRS spec leaves some ambiguity whether to allow or disallow it. This should be clarified in future revisions of the spec. Output 'Firmware Bug' for this case to encourage it to be solved in the BIOS. Signed-off-by: Mario Limonciello <mario.limonciello@amd.com> Reviewed-by: Vasant Hegde <vasant.hegde@amd.com> Link: https://lore.kernel.org/r/20250512173129.1274275-1-superm1@kernel.org Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 94a9921 commit 51c33f3

File tree

1 file changed

+28
-5
lines changed

1 file changed

+28
-5
lines changed

drivers/iommu/amd/iommu.c

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,43 @@ static inline int get_acpihid_device_id(struct device *dev,
241241
struct acpihid_map_entry **entry)
242242
{
243243
struct acpi_device *adev = ACPI_COMPANION(dev);
244-
struct acpihid_map_entry *p;
244+
struct acpihid_map_entry *p, *p1 = NULL;
245+
int hid_count = 0;
246+
bool fw_bug;
245247

246248
if (!adev)
247249
return -ENODEV;
248250

249251
list_for_each_entry(p, &acpihid_map, list) {
250252
if (acpi_dev_hid_uid_match(adev, p->hid,
251253
p->uid[0] ? p->uid : NULL)) {
252-
if (entry)
253-
*entry = p;
254-
return p->devid;
254+
p1 = p;
255+
fw_bug = false;
256+
hid_count = 1;
257+
break;
258+
}
259+
260+
/*
261+
* Count HID matches w/o UID, raise FW_BUG but allow exactly one match
262+
*/
263+
if (acpi_dev_hid_match(adev, p->hid)) {
264+
p1 = p;
265+
hid_count++;
266+
fw_bug = true;
255267
}
256268
}
257-
return -EINVAL;
269+
270+
if (!p1)
271+
return -EINVAL;
272+
if (fw_bug)
273+
dev_err_once(dev, FW_BUG "No ACPI device matched UID, but %d device%s matched HID.\n",
274+
hid_count, hid_count > 1 ? "s" : "");
275+
if (hid_count > 1)
276+
return -EINVAL;
277+
if (entry)
278+
*entry = p1;
279+
280+
return p1->devid;
258281
}
259282

260283
static inline int get_device_sbdf_id(struct device *dev)

0 commit comments

Comments
 (0)