summaryrefslogtreecommitdiff
path: root/drivers/platform/x86/amd/pmf/acpi.c
diff options
context:
space:
mode:
authorShyam Sundar S K <Shyam-sundar.S-k@amd.com>2022-08-02 20:41:47 +0530
committerHans de Goede <hdegoede@redhat.com>2022-08-15 13:23:38 +0200
commit7d77dcc83adaffacbb9000924a212566170c1257 (patch)
tree0f0b6345154d16cc7ecf1c60630f33d76cc96f5c /drivers/platform/x86/amd/pmf/acpi.c
parent3f5571d9952473c183762b801c61c42b9dbe1903 (diff)
platform/x86/amd/pmf: Handle AMT and CQL events for Auto mode
The transition to auto-mode happens when the PMF driver receives AMT (Auto Mode transition) event. transition logic will reside in the PMF driver but the events would come from other supported drivers[1]. The thermal parameters would vary between when a performance "on-lap" mode is detected and versus when not. The CQL event would get triggered from other drivers, so that PMF driver would adjust the system thermal config based on the ACPI inputs. OEMs can control whether or not to enable AMT or CQL via other supported drivers[1] but the actual transition logic resides in the AMD PMF driver. When an AMT event is received the automatic mode transition RAPL algorithm will run. When a CQL event is received an performance "on-lap" mode will be enabled and thermal parameters will be adjusted accordingly. [1] Link: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=review-hans&id=755b249250df1b612d982f3b702c831b26ecdf73 Cc: Mario Limonciello <mario.limonciello@amd.com> Cc: Mark Pearson <markpearson@lenovo.com> Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> Link: https://lore.kernel.org/r/20220802151149.2123699-10-Shyam-sundar.S-k@amd.com Reviewed-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'drivers/platform/x86/amd/pmf/acpi.c')
-rw-r--r--drivers/platform/x86/amd/pmf/acpi.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c
index 401fee381e90..cb46a7252414 100644
--- a/drivers/platform/x86/amd/pmf/acpi.c
+++ b/drivers/platform/x86/amd/pmf/acpi.c
@@ -11,6 +11,9 @@
#include <linux/acpi.h>
#include "pmf.h"
+#define APMF_CQL_NOTIFICATION 2
+#define APMF_AMT_NOTIFICATION 3
+
static union acpi_object *apmf_if_call(struct amd_pmf_dev *pdev, int fn, struct acpi_buffer *param)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -149,6 +152,48 @@ int apmf_get_auto_mode_def(struct amd_pmf_dev *pdev, struct apmf_auto_mode *data
return apmf_if_call_store_buffer(pdev, APMF_FUNC_AUTO_MODE, data, sizeof(*data));
}
+int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req)
+{
+ return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS,
+ req, sizeof(*req));
+}
+
+static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
+{
+ struct amd_pmf_dev *pmf_dev = data;
+ struct apmf_sbios_req req;
+ int ret;
+
+ mutex_lock(&pmf_dev->update_mutex);
+ ret = apmf_get_sbios_requests(pmf_dev, &req);
+ if (ret) {
+ dev_err(pmf_dev->dev, "Failed to get SBIOS requests:%d\n", ret);
+ goto out;
+ }
+
+ if (req.pending_req & BIT(APMF_AMT_NOTIFICATION)) {
+ dev_dbg(pmf_dev->dev, "AMT is supported and notifications %s\n",
+ req.amt_event ? "Enabled" : "Disabled");
+ pmf_dev->amt_enabled = !!req.amt_event;
+
+ if (pmf_dev->amt_enabled)
+ amd_pmf_handle_amt(pmf_dev);
+ else
+ amd_pmf_reset_amt(pmf_dev);
+ }
+
+ if (req.pending_req & BIT(APMF_CQL_NOTIFICATION)) {
+ dev_dbg(pmf_dev->dev, "CQL is supported and notifications %s\n",
+ req.cql_event ? "Enabled" : "Disabled");
+
+ /* update the target mode information */
+ if (pmf_dev->amt_enabled)
+ amd_pmf_update_2_cql(pmf_dev, req.cql_event);
+ }
+out:
+ mutex_unlock(&pmf_dev->update_mutex);
+}
+
static int apmf_if_verify_interface(struct amd_pmf_dev *pdev)
{
struct apmf_verify_interface output;
@@ -190,12 +235,20 @@ static int apmf_get_system_params(struct amd_pmf_dev *dev)
void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
{
+ acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+
if (pmf_dev->hb_interval)
cancel_delayed_work_sync(&pmf_dev->heart_beat);
+
+ if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
+ is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS))
+ acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler);
}
int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
{
+ acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
+ acpi_status status;
int ret;
ret = apmf_if_verify_interface(pmf_dev);
@@ -216,6 +269,20 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
schedule_delayed_work(&pmf_dev->heart_beat, 0);
}
+ /* Install the APMF Notify handler */
+ if (is_apmf_func_supported(pmf_dev, APMF_FUNC_AUTO_MODE) &&
+ is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS)) {
+ status = acpi_install_notify_handler(ahandle,
+ ACPI_ALL_NOTIFY,
+ apmf_event_handler, pmf_dev);
+ if (ACPI_FAILURE(status)) {
+ dev_err(pmf_dev->dev, "failed to install notify handler\n");
+ return -ENODEV;
+ }
+ /* Call the handler once manually to catch up with possibly missed notifies. */
+ apmf_event_handler(ahandle, 0, pmf_dev);
+ }
+
out:
return ret;
}