commit a412caea5a2d ("ACPI: bus: Allow negotiating _OSC capabilities") added support for `acpi_run_osc` to return `AE_SUPPORT` when negotiating an _OSC. This was fixed in other kernel consumers, but `acpi_pci_run_osc` was missed. Update the function to detect when called with `OSC_QUERY_ENABLE` set and attempt to negotiate up to 5 times. Reported-by: Qian Cai <quic_qiancai@xxxxxxxxxxx> Fixes: a412caea5a2d ("ACPI: bus: Allow negotiating _OSC capabilities") Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx> --- drivers/acpi/pci_root.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 6f9e75d14808..2eda355fde57 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -171,7 +171,7 @@ static void decode_osc_control(struct acpi_pci_root *root, char *msg, u32 word) static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; static acpi_status acpi_pci_run_osc(acpi_handle handle, - const u32 *capbuf, u32 *retval) + u32 *capbuf, u32 *retval) { struct acpi_osc_context context = { .uuid_str = pci_osc_uuid_str, @@ -180,7 +180,26 @@ static acpi_status acpi_pci_run_osc(acpi_handle handle, .cap.pointer = (void *)capbuf, }; acpi_status status; + u32 *capbuf_ret; + int i; + + if (!(capbuf[OSC_QUERY_DWORD] & OSC_QUERY_ENABLE)) + goto skip_negotiate; + for (i = 0; i < 5; i++) { + status = acpi_run_osc(handle, &context); + if (status == AE_OK || status == AE_SUPPORT) { + capbuf_ret = context.ret.pointer; + capbuf[OSC_SUPPORT_DWORD] = capbuf_ret[OSC_SUPPORT_DWORD]; + kfree(context.ret.pointer); + } + if (status != AE_SUPPORT) + break; + } + if (ACPI_FAILURE(status)) + return status; +skip_negotiate: + capbuf[OSC_QUERY_DWORD] = 0; status = acpi_run_osc(handle, &context); if (ACPI_SUCCESS(status)) { *retval = *((u32 *)(context.ret.pointer + 8)); -- 2.34.1