1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2005 Intel Corporation 4 * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. 5 * 6 * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> 7 * - Added _PDC for platforms with Intel CPUs 8 */ 9 10 #define pr_fmt(fmt) "ACPI: " fmt 11 12 #include <linux/slab.h> 13 #include <linux/acpi.h> 14 #include <acpi/processor.h> 15 16 #include "internal.h" 17 18 static void acpi_set_pdc_bits(u32 *buf) 19 { 20 buf[0] = ACPI_PDC_REVISION_ID; 21 buf[1] = 1; 22 buf[2] = 0; 23 24 /* Twiddle arch-specific bits needed for _PDC */ 25 arch_acpi_set_proc_cap_bits(&buf[2]); 26 } 27 28 static struct acpi_object_list *acpi_processor_alloc_pdc(void) 29 { 30 struct acpi_object_list *obj_list; 31 union acpi_object *obj; 32 u32 *buf; 33 34 /* allocate and initialize pdc. It will be used later. */ 35 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); 36 if (!obj_list) 37 goto out; 38 39 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); 40 if (!obj) { 41 kfree(obj_list); 42 goto out; 43 } 44 45 buf = kmalloc(12, GFP_KERNEL); 46 if (!buf) { 47 kfree(obj); 48 kfree(obj_list); 49 goto out; 50 } 51 52 acpi_set_pdc_bits(buf); 53 54 obj->type = ACPI_TYPE_BUFFER; 55 obj->buffer.length = 12; 56 obj->buffer.pointer = (u8 *) buf; 57 obj_list->count = 1; 58 obj_list->pointer = obj; 59 60 return obj_list; 61 out: 62 pr_err("Memory allocation error\n"); 63 return NULL; 64 } 65 66 /* 67 * _PDC is required for a BIOS-OS handshake for most of the newer 68 * ACPI processor features. 69 */ 70 static acpi_status 71 acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) 72 { 73 acpi_status status = AE_OK; 74 75 status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); 76 77 if (ACPI_FAILURE(status)) 78 acpi_handle_debug(handle, 79 "Could not evaluate _PDC, using legacy perf control\n"); 80 81 return status; 82 } 83 84 void acpi_processor_set_pdc(acpi_handle handle) 85 { 86 struct acpi_object_list *obj_list; 87 88 if (arch_has_acpi_pdc() == false) 89 return; 90 91 obj_list = acpi_processor_alloc_pdc(); 92 if (!obj_list) 93 return; 94 95 acpi_processor_eval_pdc(handle, obj_list); 96 97 kfree(obj_list->pointer->buffer.pointer); 98 kfree(obj_list->pointer); 99 kfree(obj_list); 100 } 101 102 static acpi_status __init 103 early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) 104 { 105 if (processor_physically_present(handle) == false) 106 return AE_OK; 107 108 acpi_processor_set_pdc(handle); 109 return AE_OK; 110 } 111 112 void __init acpi_early_processor_set_pdc(void) 113 { 114 acpi_proc_quirk_mwait_check(); 115 116 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, 117 ACPI_UINT32_MAX, 118 early_init_pdc, NULL, NULL, NULL); 119 acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); 120 } 121