From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-20.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70A65C07E99 for ; Mon, 5 Jul 2021 15:35:12 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 50F16601FD for ; Mon, 5 Jul 2021 15:35:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232827AbhGEPhq (ORCPT ); Mon, 5 Jul 2021 11:37:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:58844 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233257AbhGEPfV (ORCPT ); Mon, 5 Jul 2021 11:35:21 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 0EE7A61986; Mon, 5 Jul 2021 15:31:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1625499099; bh=IrBPAoFZwjddYZY2UoNcL72MH2hgB2RKDn/JjljfwnM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fWJ/P5sqMr3Wy5xjn7qBtWrgRlcagfU/4VO1jWJgIOxtcxN7g4mrtSNrvt1CR5zo3 8Dcm4PBMT3JZZJ8bUZSPB6URNs3fyQZUktuABWktDApkHmf0PB/vC2r38e4uasiWA7 w7e6jf3R8RHsKrbl+cgONHmIlx+1Cq31CQXH6B06barMd12i3U/5wluXwnLpYJh02+ PPR0VAIovEKXTK4Y6HfyRgPDIpxIdJPpQvk7E1RaPq9Tixkk1lZ354aUpZ7cEX/WyW jv7tNz4/MXlu3fKMPxX3tc32JqvBR1iXaVVVhpadqr+hEN86Y8lLbIX3DD1J71hSy1 c35WmXTc4QmOQ== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Mario Limonciello , Prike Liang , Alex Deucher , "Rafael J . Wysocki" , Sasha Levin , linux-acpi@vger.kernel.org Subject: [PATCH AUTOSEL 4.14 02/15] ACPI: processor idle: Fix up C-state latency if not ordered Date: Mon, 5 Jul 2021 11:31:23 -0400 Message-Id: <20210705153136.1522245-2-sashal@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210705153136.1522245-1-sashal@kernel.org> References: <20210705153136.1522245-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mario Limonciello [ Upstream commit 65ea8f2c6e230bdf71fed0137cf9e9d1b307db32 ] Generally, the C-state latency is provided by the _CST method or FADT, but some OEM platforms using AMD Picasso, Renoir, Van Gogh, and Cezanne set the C2 latency greater than C3's which causes the C2 state to be skipped. That will block the core entering PC6, which prevents S0ix working properly on Linux systems. In other operating systems, the latency values are not validated and this does not cause problems by skipping states. To avoid this issue on Linux, detect when latencies are not an arithmetic progression and sort them. Link: https://gitlab.freedesktop.org/agd5f/linux/-/commit/026d186e4592c1ee9c1cb44295912d0294508725 Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1230#note_712174 Suggested-by: Prike Liang Suggested-by: Alex Deucher Signed-off-by: Mario Limonciello [ rjw: Subject and changelog edits ] Signed-off-by: Rafael J. Wysocki Signed-off-by: Sasha Levin --- drivers/acpi/processor_idle.c | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d50a7b6ccddd..590eeca2419f 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -29,6 +29,7 @@ #include #include #include /* need_resched() */ +#include #include #include #include @@ -540,10 +541,37 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, return; } +static int acpi_cst_latency_cmp(const void *a, const void *b) +{ + const struct acpi_processor_cx *x = a, *y = b; + + if (!(x->valid && y->valid)) + return 0; + if (x->latency > y->latency) + return 1; + if (x->latency < y->latency) + return -1; + return 0; +} +static void acpi_cst_latency_swap(void *a, void *b, int n) +{ + struct acpi_processor_cx *x = a, *y = b; + u32 tmp; + + if (!(x->valid && y->valid)) + return; + tmp = x->latency; + x->latency = y->latency; + y->latency = tmp; +} + static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; + unsigned int last_latency = 0; + unsigned int last_type = 0; + bool buggy_latency = false; pr->power.timer_broadcast_on_state = INT_MAX; @@ -567,12 +595,24 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) } if (!cx->valid) continue; + if (cx->type >= last_type && cx->latency < last_latency) + buggy_latency = true; + last_latency = cx->latency; + last_type = cx->type; lapic_timer_check_state(i, pr, cx); tsc_check_state(cx->type); working++; } + if (buggy_latency) { + pr_notice("FW issue: working around C-state latencies out of order\n"); + sort(&pr->power.states[1], max_cstate, + sizeof(struct acpi_processor_cx), + acpi_cst_latency_cmp, + acpi_cst_latency_swap); + } + lapic_timer_propagate_broadcast(pr); return (working); -- 2.30.2