Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 2 : : /* 3 : : * acpi_lpat.c - LPAT table processing functions 4 : : * 5 : : * Copyright (C) 2015 Intel Corporation. All rights reserved. 6 : : */ 7 : : 8 : : #include <linux/export.h> 9 : : #include <linux/acpi.h> 10 : : #include <acpi/acpi_lpat.h> 11 : : 12 : : /** 13 : : * acpi_lpat_raw_to_temp(): Return temperature from raw value through 14 : : * LPAT conversion table 15 : : * 16 : : * @lpat_table: the temperature_raw mapping table structure 17 : : * @raw: the raw value, used as a key to get the temperature from the 18 : : * above mapping table 19 : : * 20 : : * A positive converted temperature value will be returned on success, 21 : : * a negative errno will be returned in error cases. 22 : : */ 23 : 0 : int acpi_lpat_raw_to_temp(struct acpi_lpat_conversion_table *lpat_table, 24 : : int raw) 25 : : { 26 : 0 : int i, delta_temp, delta_raw, temp; 27 : 0 : struct acpi_lpat *lpat = lpat_table->lpat; 28 : : 29 [ # # ]: 0 : for (i = 0; i < lpat_table->lpat_count - 1; i++) { 30 [ # # # # : 0 : if ((raw >= lpat[i].raw && raw <= lpat[i+1].raw) || # # ] 31 [ # # ]: 0 : (raw <= lpat[i].raw && raw >= lpat[i+1].raw)) 32 : : break; 33 : : } 34 : : 35 [ # # ]: 0 : if (i == lpat_table->lpat_count - 1) 36 : : return -ENOENT; 37 : : 38 : 0 : delta_temp = lpat[i+1].temp - lpat[i].temp; 39 : 0 : delta_raw = lpat[i+1].raw - lpat[i].raw; 40 : 0 : temp = lpat[i].temp + (raw - lpat[i].raw) * delta_temp / delta_raw; 41 : : 42 : 0 : return temp; 43 : : } 44 : : EXPORT_SYMBOL_GPL(acpi_lpat_raw_to_temp); 45 : : 46 : : /** 47 : : * acpi_lpat_temp_to_raw(): Return raw value from temperature through 48 : : * LPAT conversion table 49 : : * 50 : : * @lpat_table: the temperature_raw mapping table 51 : : * @temp: the temperature, used as a key to get the raw value from the 52 : : * above mapping table 53 : : * 54 : : * The raw value will be returned on success, 55 : : * a negative errno will be returned in error cases. 56 : : */ 57 : 0 : int acpi_lpat_temp_to_raw(struct acpi_lpat_conversion_table *lpat_table, 58 : : int temp) 59 : : { 60 : 0 : int i, delta_temp, delta_raw, raw; 61 : 0 : struct acpi_lpat *lpat = lpat_table->lpat; 62 : : 63 [ # # ]: 0 : for (i = 0; i < lpat_table->lpat_count - 1; i++) { 64 [ # # # # ]: 0 : if (temp >= lpat[i].temp && temp <= lpat[i+1].temp) 65 : : break; 66 : : } 67 : : 68 [ # # ]: 0 : if (i == lpat_table->lpat_count - 1) 69 : : return -ENOENT; 70 : : 71 : 0 : delta_temp = lpat[i+1].temp - lpat[i].temp; 72 : 0 : delta_raw = lpat[i+1].raw - lpat[i].raw; 73 : 0 : raw = lpat[i].raw + (temp - lpat[i].temp) * delta_raw / delta_temp; 74 : : 75 : 0 : return raw; 76 : : } 77 : : EXPORT_SYMBOL_GPL(acpi_lpat_temp_to_raw); 78 : : 79 : : /** 80 : : * acpi_lpat_get_conversion_table(): Parse ACPI LPAT table if present. 81 : : * 82 : : * @handle: Handle to acpi device 83 : : * 84 : : * Parse LPAT table to a struct of type acpi_lpat_table. On success 85 : : * it returns a pointer to newly allocated table. This table must 86 : : * be freed by the caller when finished processing, using a call to 87 : : * acpi_lpat_free_conversion_table. 88 : : */ 89 : 0 : struct acpi_lpat_conversion_table *acpi_lpat_get_conversion_table(acpi_handle 90 : : handle) 91 : : { 92 : 0 : struct acpi_lpat_conversion_table *lpat_table = NULL; 93 : 0 : struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 94 : 0 : union acpi_object *obj_p, *obj_e; 95 : 0 : int *lpat, i; 96 : 0 : acpi_status status; 97 : : 98 : 0 : status = acpi_evaluate_object(handle, "LPAT", NULL, &buffer); 99 [ # # ]: 0 : if (ACPI_FAILURE(status)) 100 : : return NULL; 101 : : 102 : 0 : obj_p = (union acpi_object *)buffer.pointer; 103 [ # # # # ]: 0 : if (!obj_p || (obj_p->type != ACPI_TYPE_PACKAGE) || 104 [ # # ]: 0 : (obj_p->package.count % 2) || (obj_p->package.count < 4)) 105 : 0 : goto out; 106 : : 107 : 0 : lpat = kcalloc(obj_p->package.count, sizeof(int), GFP_KERNEL); 108 [ # # ]: 0 : if (!lpat) 109 : 0 : goto out; 110 : : 111 [ # # ]: 0 : for (i = 0; i < obj_p->package.count; i++) { 112 : 0 : obj_e = &obj_p->package.elements[i]; 113 [ # # ]: 0 : if (obj_e->type != ACPI_TYPE_INTEGER) { 114 : 0 : kfree(lpat); 115 : 0 : goto out; 116 : : } 117 : 0 : lpat[i] = (s64)obj_e->integer.value; 118 : : } 119 : : 120 : 0 : lpat_table = kzalloc(sizeof(*lpat_table), GFP_KERNEL); 121 [ # # ]: 0 : if (!lpat_table) { 122 : 0 : kfree(lpat); 123 : 0 : goto out; 124 : : } 125 : : 126 : 0 : lpat_table->lpat = (struct acpi_lpat *)lpat; 127 : 0 : lpat_table->lpat_count = obj_p->package.count / 2; 128 : : 129 : 0 : out: 130 : 0 : kfree(buffer.pointer); 131 : 0 : return lpat_table; 132 : : } 133 : : EXPORT_SYMBOL_GPL(acpi_lpat_get_conversion_table); 134 : : 135 : : /** 136 : : * acpi_lpat_free_conversion_table(): Free LPAT table. 137 : : * 138 : : * @lpat_table: the temperature_raw mapping table structure 139 : : * 140 : : * Frees the LPAT table previously allocated by a call to 141 : : * acpi_lpat_get_conversion_table. 142 : : */ 143 : 0 : void acpi_lpat_free_conversion_table(struct acpi_lpat_conversion_table 144 : : *lpat_table) 145 : : { 146 [ # # ]: 0 : if (lpat_table) { 147 : 0 : kfree(lpat_table->lpat); 148 : 0 : kfree(lpat_table); 149 : : } 150 : 0 : } 151 : : EXPORT_SYMBOL_GPL(acpi_lpat_free_conversion_table);