1#include <linux/errno.h> 2#include "linux/delay.h" 3#include "hwmgr.h" 4#include "amd_acpi.h" 5 6bool acpi_atcs_functions_supported(void *device, uint32_t index) 7{ 8 int32_t result; 9 struct atcs_verify_interface output_buf = {0}; 10 11 int32_t temp_buffer = 1; 12 13 result = cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS, 14 ATCS_FUNCTION_VERIFY_INTERFACE, 15 &temp_buffer, 16 &output_buf, 17 1, 18 sizeof(temp_buffer), 19 sizeof(output_buf)); 20 21 return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false; 22} 23 24int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) 25{ 26 struct atcs_pref_req_input atcs_input; 27 struct atcs_pref_req_output atcs_output; 28 u32 retry = 3; 29 int result; 30 struct cgs_system_info info = {0}; 31 32 if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST)) 33 return -EINVAL; 34 35 info.size = sizeof(struct cgs_system_info); 36 info.info_id = CGS_SYSTEM_INFO_ADAPTER_BDF_ID; 37 result = cgs_query_system_info(device, &info); 38 if (result != 0) 39 return -EINVAL; 40 atcs_input.client_id = (uint16_t)info.value; 41 atcs_input.size = sizeof(struct atcs_pref_req_input); 42 atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK; 43 atcs_input.flags = ATCS_WAIT_FOR_COMPLETION; 44 if (advertise) 45 atcs_input.flags |= ATCS_ADVERTISE_CAPS; 46 atcs_input.req_type = ATCS_PCIE_LINK_SPEED; 47 atcs_input.perf_req = perf_req; 48 49 atcs_output.size = sizeof(struct atcs_pref_req_input); 50 51 while (retry--) { 52 result = cgs_call_acpi_method(device, 53 CGS_ACPI_METHOD_ATCS, 54 ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, 55 &atcs_input, 56 &atcs_output, 57 0, 58 sizeof(atcs_input), 59 sizeof(atcs_output)); 60 if (result != 0) 61 return -EIO; 62 63 switch (atcs_output.ret_val) { 64 case ATCS_REQUEST_REFUSED: 65 default: 66 return -EINVAL; 67 case ATCS_REQUEST_COMPLETE: 68 return 0; 69 case ATCS_REQUEST_IN_PROGRESS: 70 udelay(10); 71 break; 72 } 73 } 74 75 return 0; 76} 77