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 23 /* Twiddle arch-specific bits needed for _PDC */ 24 arch_acpi_set_proc_cap_bits(&buf[2]); 25 } 26 27 static struct acpi_object_list *acpi_processor_alloc_pdc(void) 28 { 29 struct acpi_object_list *obj_list; 30 union acpi_object *obj; 31 u32 *buf; 32 33 /* allocate and initialize pdc. It will be used later. */ 34 obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); 35 if (!obj_list) 36 goto out; 37 38 obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); 39 if (!obj) { 40 kfree(obj_list); 41 goto out; 42 } 43 44 buf = kmalloc(12, GFP_KERNEL); 45 if (!buf) { 46 kfree(obj); 47 kfree(obj_list); 48 goto out; 49 } 50 51 acpi_set_pdc_bits(buf); 52 53 obj->type = ACPI_TYPE_BUFFER; 54 obj->buffer.length = 12; 55 obj->buffer.pointer = (u8 *) buf; 56 obj_list->count = 1; 57 obj_list->pointer = obj; 58 59 return obj_list; 60 out: 61 pr_err("Memory allocation error\n"); 62 return NULL; 63 } 64 65 /* 66 * _PDC is required for a BIOS-OS handshake for most of the newer 67 * ACPI processor features. 68 */ 69 static acpi_status 70 acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) 71 { 72 acpi_status status = AE_OK; 73 74 status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); 75 76 if (ACPI_FAILURE(status)) 77 acpi_handle_debug(handle, 78 "Could not evaluate _PDC, using legacy perf control\n"); 79 80 return status; 81 } 82 83 void acpi_processor_set_pdc(acpi_handle handle) 84 { 85 struct acpi_object_list *obj_list; 86 87 if (arch_has_acpi_pdc() == false) 88 return; 89 90 obj_list = acpi_processor_alloc_pdc(); 91 if (!obj_list) 92 return; 93 94 acpi_processor_eval_pdc(handle, obj_list); 95 96 kfree(obj_list->pointer->buffer.pointer); 97 kfree(obj_list->pointer); 98 kfree(obj_list); 99 } 100 101 static acpi_status __init 102 early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) 103 { 104 if (processor_physically_present(handle) == false) 105 return AE_OK; 106 107 acpi_processor_set_pdc(handle); 108 return AE_OK; 109 } 110 111 void __init acpi_early_processor_set_pdc(void) 112 { 113 acpi_proc_quirk_mwait_check(); 114 115 acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, 116 ACPI_UINT32_MAX, 117 early_init_pdc, NULL, NULL, NULL); 118 acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, early_init_pdc, NULL, NULL); 119 } 120