Unverified Commit 04199ef4 authored by Shyam Sundar S K's avatar Shyam Sundar S K Committed by Ilpo Järvinen
Browse files

platform/x86/amd/pmf: Add custom BIOS input support for AMD_CPU_ID_PS



The PMF ACPI Specification (APMF) has been revised to version 1.3 to allow
for additional custom BIOS inputs, enabling OEMs to have more precise
thermal management of the system. This update includes adding support to
the driver using the new data structure received from the BIOS through the
existing APMF interfaces.

Co-developed-by: default avatarPatil Rajesh Reddy <Patil.Reddy@amd.com>
Signed-off-by: default avatarPatil Rajesh Reddy <Patil.Reddy@amd.com>
Tested-by: default avatarYijun Shen <Yijun.Shen@Dell.com>
Signed-off-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Link: https://patch.msgid.link/20250901110140.2519072-7-Shyam-sundar.S-k@amd.com


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
parent 4389d380
Loading
Loading
Loading
Loading
+53 −5
Original line number Diff line number Diff line
@@ -320,6 +320,11 @@ int apmf_get_sbios_requests_v2(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v
	return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req));
}

int apmf_get_sbios_requests_v1(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v1 *req)
{
	return apmf_if_call_store_buffer(pdev, APMF_FUNC_SBIOS_REQUESTS, req, sizeof(*req));
}

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,
@@ -338,6 +343,18 @@ static void apmf_event_handler_v2(acpi_handle handle, u32 event, void *data)
		dev_err(pmf_dev->dev, "Failed to get v2 SBIOS requests: %d\n", ret);
}

static void apmf_event_handler_v1(acpi_handle handle, u32 event, void *data)
{
	struct amd_pmf_dev *pmf_dev = data;
	int ret;

	guard(mutex)(&pmf_dev->cb_mutex);

	ret = apmf_get_sbios_requests_v1(pmf_dev, &pmf_dev->req1);
	if (ret)
		dev_err(pmf_dev->dev, "Failed to get v1 SBIOS requests: %d\n", ret);
}

static void apmf_event_handler(acpi_handle handle, u32 event, void *data)
{
	struct amd_pmf_dev *pmf_dev = data;
@@ -427,6 +444,11 @@ int apmf_get_dyn_slider_def_dc(struct amd_pmf_dev *pdev, struct apmf_dyn_slider_
	return apmf_if_call_store_buffer(pdev, APMF_FUNC_DYN_SLIDER_DC, data, sizeof(*data));
}

static apmf_event_handler_t apmf_event_handlers[] = {
	[PMF_IF_V1] = apmf_event_handler_v1,
	[PMF_IF_V2] = apmf_event_handler_v2,
};

int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
{
	acpi_handle ahandle = ACPI_HANDLE(pmf_dev->dev);
@@ -446,13 +468,26 @@ int apmf_install_handler(struct amd_pmf_dev *pmf_dev)
		apmf_event_handler(ahandle, 0, pmf_dev);
	}

	if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2) {
	if (!pmf_dev->smart_pc_enabled)
		return -EINVAL;

	switch (pmf_dev->pmf_if_version) {
	case PMF_IF_V1:
		if (!is_apmf_bios_input_notifications_supported(pmf_dev))
			break;
		fallthrough;
	case PMF_IF_V2:
		status = acpi_install_notify_handler(ahandle, ACPI_ALL_NOTIFY,
						     apmf_event_handler_v2, pmf_dev);
				apmf_event_handlers[pmf_dev->pmf_if_version], pmf_dev);
		if (ACPI_FAILURE(status)) {
			dev_err(pmf_dev->dev, "failed to install notify handler for custom BIOS inputs\n");
			dev_err(pmf_dev->dev,
				"failed to install notify handler v%d for custom BIOS inputs\n",
				pmf_dev->pmf_if_version);
			return -ENODEV;
		}
		break;
	default:
		break;
	}

	return 0;
@@ -506,8 +541,21 @@ void apmf_acpi_deinit(struct amd_pmf_dev *pmf_dev)
	    is_apmf_func_supported(pmf_dev, APMF_FUNC_SBIOS_REQUESTS))
		acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler);

	if (pmf_dev->smart_pc_enabled && pmf_dev->pmf_if_version == PMF_IF_V2)
		acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY, apmf_event_handler_v2);
	if (!pmf_dev->smart_pc_enabled)
		return;

	switch (pmf_dev->pmf_if_version) {
	case PMF_IF_V1:
		if (!is_apmf_bios_input_notifications_supported(pmf_dev))
			break;
		fallthrough;
	case PMF_IF_V2:
		acpi_remove_notify_handler(ahandle, ACPI_ALL_NOTIFY,
					   apmf_event_handlers[pmf_dev->pmf_if_version]);
		break;
	default:
		break;
	}
}

int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
+22 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ struct cookie_header {
#define APTS_MAX_STATES		16
#define CUSTOM_BIOS_INPUT_BITS	GENMASK(16, 7)

typedef void (*apmf_event_handler_t)(acpi_handle handle, u32 event, void *data);

/* APTS PMF BIOS Interface */
struct amd_pmf_apts_output {
	u16 table_version;
@@ -187,6 +189,24 @@ struct apmf_sbios_req {
	u8 skin_temp_hs2;
} __packed;

/* As per APMF spec 1.3 */
struct apmf_sbios_req_v1 {
	u16 size;
	u32 pending_req;
	u8 rsvd;
	u8 cql_event;
	u8 amt_event;
	u32 fppt;
	u32 sppt;
	u32 sppt_apu_only;
	u32 spl;
	u32 stt_min_limit;
	u8 skin_temp_apu;
	u8 skin_temp_hs2;
	u8 enable_cnqf;
	u32 custom_policy[10];
} __packed;

struct apmf_sbios_req_v2 {
	u16 size;
	u32 pending_req;
@@ -379,6 +399,7 @@ struct amd_pmf_dev {
	struct apmf_sbios_req_v2 req; /* To get custom bios pending request */
	struct mutex cb_mutex;
	u32 notifications;
	struct apmf_sbios_req_v1 req1;
};

struct apmf_sps_prop_granular_v2 {
@@ -835,6 +856,7 @@ void amd_pmf_init_auto_mode(struct amd_pmf_dev *dev);
void amd_pmf_deinit_auto_mode(struct amd_pmf_dev *dev);
void amd_pmf_trans_automode(struct amd_pmf_dev *dev, int socket_power, ktime_t time_elapsed_ms);
int apmf_get_sbios_requests(struct amd_pmf_dev *pdev, struct apmf_sbios_req *req);
int apmf_get_sbios_requests_v1(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v1 *req);
int apmf_get_sbios_requests_v2(struct amd_pmf_dev *pdev, struct apmf_sbios_req_v2 *req);

void amd_pmf_update_2_cql(struct amd_pmf_dev *dev, bool is_cql_event);
+30 −6
Original line number Diff line number Diff line
@@ -132,22 +132,46 @@ static void amd_pmf_set_ta_custom_bios_input(struct ta_pmf_enact_table *in, int
	}
}

static void amd_pmf_update_bios_inputs(struct amd_pmf_dev *pdev, u32 pending_req,
				       const struct amd_pmf_pb_bitmap *inputs,
				       const u32 *custom_policy, struct ta_pmf_enact_table *in)
{
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) {
		if (!(pending_req & inputs[i].bit_mask))
			continue;
		amd_pmf_set_ta_custom_bios_input(in, i, custom_policy[i]);
	}
}

static void amd_pmf_get_custom_bios_inputs(struct amd_pmf_dev *pdev,
					   struct ta_pmf_enact_table *in)
{
	unsigned int i;
	if (!(pdev->req.pending_req || pdev->req1.pending_req))
		return;

	if (!pdev->req.pending_req)
	if (!pdev->smart_pc_enabled)
		return;

	for (i = 0; i < ARRAY_SIZE(custom_bios_inputs); i++) {
		if (!(pdev->req.pending_req & custom_bios_inputs[i].bit_mask))
			continue;
		amd_pmf_set_ta_custom_bios_input(in, i, pdev->req.custom_policy[i]);
	switch (pdev->pmf_if_version) {
	case PMF_IF_V1:
		if (!is_apmf_bios_input_notifications_supported(pdev))
			return;
		amd_pmf_update_bios_inputs(pdev, pdev->req1.pending_req, custom_bios_inputs_v1,
					   pdev->req1.custom_policy, in);
		break;
	case PMF_IF_V2:
		amd_pmf_update_bios_inputs(pdev, pdev->req.pending_req, custom_bios_inputs,
					   pdev->req.custom_policy, in);
		break;
	default:
		break;
	}

	/* Clear pending requests after handling */
	memset(&pdev->req, 0, sizeof(pdev->req));
	memset(&pdev->req1, 0, sizeof(pdev->req1));
}

static void amd_pmf_get_c0_residency(u16 *core_res, size_t size, struct ta_pmf_enact_table *in)