diff options
| -rw-r--r-- | drivers/platform/x86/amd/pmf/acpi.c | 58 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/pmf.h | 22 | ||||
| -rw-r--r-- | drivers/platform/x86/amd/pmf/spc.c | 36 | 
3 files changed, 105 insertions, 11 deletions
| diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c index 4982311ac045..41c34c26ceec 100644 --- a/drivers/platform/x86/amd/pmf/acpi.c +++ b/drivers/platform/x86/amd/pmf/acpi.c @@ -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) diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 6ddd1a6e9115..647993e94674 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -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); diff --git a/drivers/platform/x86/amd/pmf/spc.c b/drivers/platform/x86/amd/pmf/spc.c index 06b7760b2a8b..1b612e79a3d8 100644 --- a/drivers/platform/x86/amd/pmf/spc.c +++ b/drivers/platform/x86/amd/pmf/spc.c @@ -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) | 
