Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

platform/x86/intel-uncore-freq: Add support for efficiency latency control

Add efficiency latency control support to the TPMI uncore driver. This
defines two new threshold values for controlling uncore frequency, low
threshold and high threshold. When CPU utilization is below low threshold,
the user configurable floor latency control frequency can be used by the
system. When CPU utilization is above high threshold, the uncore frequency
is increased in 100MHz steps until power limit is reached.

Signed-off-by: Tero Kristo <tero.kristo@linux.intel.com>
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20240828153657.1296410-3-tero.kristo@linux.intel.com
Signed-off-by: Hans de Goede <hdegoede@redhat.com>

authored by

Tero Kristo and committed by
Hans de Goede
bb516dc7 8022ae2c

+160 -2
+4
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.h
··· 70 70 UNCORE_INDEX_MIN_FREQ, 71 71 UNCORE_INDEX_MAX_FREQ, 72 72 UNCORE_INDEX_CURRENT_FREQ, 73 + UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD, 74 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD, 75 + UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, 76 + UNCORE_INDEX_EFF_LAT_CTRL_FREQ, 73 77 }; 74 78 75 79 int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value,
+156 -2
drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
··· 30 30 31 31 #define UNCORE_MAJOR_VERSION 0 32 32 #define UNCORE_MINOR_VERSION 2 33 + #define UNCORE_ELC_SUPPORTED_VERSION 2 33 34 #define UNCORE_HEADER_INDEX 0 34 35 #define UNCORE_FABRIC_CLUSTER_OFFSET 8 35 36 ··· 47 46 /* Information for each cluster */ 48 47 struct tpmi_uncore_cluster_info { 49 48 bool root_domain; 49 + bool elc_supported; 50 50 u8 __iomem *cluster_base; 51 51 struct uncore_data uncore_data; 52 52 struct tpmi_uncore_struct *uncore_root; ··· 77 75 /* Bit definitions for CONTROL register */ 78 76 #define UNCORE_MAX_RATIO_MASK GENMASK_ULL(14, 8) 79 77 #define UNCORE_MIN_RATIO_MASK GENMASK_ULL(21, 15) 78 + #define UNCORE_EFF_LAT_CTRL_RATIO_MASK GENMASK_ULL(28, 22) 79 + #define UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK GENMASK_ULL(38, 32) 80 + #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE BIT(39) 81 + #define UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK GENMASK_ULL(46, 40) 80 82 81 83 /* Helper function to read MMIO offset for max/min control frequency */ 82 84 static void read_control_freq(struct tpmi_uncore_cluster_info *cluster_info, ··· 93 87 *value = FIELD_GET(UNCORE_MAX_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; 94 88 else 95 89 *value = FIELD_GET(UNCORE_MIN_RATIO_MASK, control) * UNCORE_FREQ_KHZ_MULTIPLIER; 90 + } 91 + 92 + /* Helper function to read efficiency latency control values over MMIO */ 93 + static int read_eff_lat_ctrl(struct uncore_data *data, unsigned int *val, enum uncore_index index) 94 + { 95 + struct tpmi_uncore_cluster_info *cluster_info; 96 + u64 ctrl; 97 + 98 + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); 99 + if (cluster_info->root_domain) 100 + return -ENODATA; 101 + 102 + if (!cluster_info->elc_supported) 103 + return -EOPNOTSUPP; 104 + 105 + ctrl = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 106 + 107 + switch (index) { 108 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 109 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, ctrl); 110 + *val *= 100; 111 + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK)); 112 + break; 113 + 114 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 115 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, ctrl); 116 + *val *= 100; 117 + *val = DIV_ROUND_UP(*val, FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK)); 118 + break; 119 + 120 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 121 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, ctrl); 122 + break; 123 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 124 + *val = FIELD_GET(UNCORE_EFF_LAT_CTRL_RATIO_MASK, ctrl) * UNCORE_FREQ_KHZ_MULTIPLIER; 125 + break; 126 + 127 + default: 128 + return -EOPNOTSUPP; 129 + } 130 + 131 + return 0; 96 132 } 97 133 98 134 #define UNCORE_MAX_RATIO FIELD_MAX(UNCORE_MAX_RATIO_MASK) ··· 185 137 return 0; 186 138 } 187 139 140 + /* Helper function for writing efficiency latency control values over MMIO */ 141 + static int write_eff_lat_ctrl(struct uncore_data *data, unsigned int val, enum uncore_index index) 142 + { 143 + struct tpmi_uncore_cluster_info *cluster_info; 144 + u64 control; 145 + 146 + cluster_info = container_of(data, struct tpmi_uncore_cluster_info, uncore_data); 147 + 148 + if (cluster_info->root_domain) 149 + return -ENODATA; 150 + 151 + if (!cluster_info->elc_supported) 152 + return -EOPNOTSUPP; 153 + 154 + switch (index) { 155 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 156 + if (val > 100) 157 + return -EINVAL; 158 + break; 159 + 160 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 161 + if (val > 100) 162 + return -EINVAL; 163 + break; 164 + 165 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 166 + if (val > 1) 167 + return -EINVAL; 168 + break; 169 + 170 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 171 + val /= UNCORE_FREQ_KHZ_MULTIPLIER; 172 + if (val > FIELD_MAX(UNCORE_EFF_LAT_CTRL_RATIO_MASK)) 173 + return -EINVAL; 174 + break; 175 + 176 + default: 177 + return -EOPNOTSUPP; 178 + } 179 + 180 + control = readq(cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 181 + 182 + switch (index) { 183 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 184 + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK); 185 + val /= 100; 186 + control &= ~UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK; 187 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASK, val); 188 + break; 189 + 190 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 191 + val *= FIELD_MAX(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK); 192 + val /= 100; 193 + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK; 194 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASK, val); 195 + break; 196 + 197 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 198 + control &= ~UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE; 199 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE, val); 200 + break; 201 + 202 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 203 + control &= ~UNCORE_EFF_LAT_CTRL_RATIO_MASK; 204 + control |= FIELD_PREP(UNCORE_EFF_LAT_CTRL_RATIO_MASK, val); 205 + break; 206 + 207 + default: 208 + break; 209 + } 210 + 211 + writeq(control, cluster_info->cluster_base + UNCORE_CONTROL_INDEX); 212 + 213 + return 0; 214 + } 215 + 188 216 /* Helper function to write MMIO offset for max/min control frequency */ 189 217 static void write_control_freq(struct tpmi_uncore_cluster_info *cluster_info, unsigned int input, 190 218 unsigned int index) ··· 280 156 writeq(control, (cluster_info->cluster_base + UNCORE_CONTROL_INDEX)); 281 157 } 282 158 283 - /* Callback for sysfs write for max/min frequencies. Called under mutex locks */ 159 + /* Helper for sysfs write for max/min frequencies. Called under mutex locks */ 284 160 static int uncore_write_control_freq(struct uncore_data *data, unsigned int input, 285 161 enum uncore_index index) 286 162 { ··· 358 234 case UNCORE_INDEX_CURRENT_FREQ: 359 235 return uncore_read_freq(data, value); 360 236 237 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 238 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 239 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 240 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 241 + return read_eff_lat_ctrl(data, value, index); 242 + 243 + default: 244 + break; 245 + } 246 + 247 + return -EOPNOTSUPP; 248 + } 249 + 250 + /* Callback for sysfs write for TPMI uncore data. Called under mutex locks. */ 251 + static int uncore_write(struct uncore_data *data, unsigned int value, enum uncore_index index) 252 + { 253 + switch (index) { 254 + case UNCORE_INDEX_EFF_LAT_CTRL_LOW_THRESHOLD: 255 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD: 256 + case UNCORE_INDEX_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLE: 257 + case UNCORE_INDEX_EFF_LAT_CTRL_FREQ: 258 + return write_eff_lat_ctrl(data, value, index); 259 + 260 + case UNCORE_INDEX_MIN_FREQ: 261 + case UNCORE_INDEX_MAX_FREQ: 262 + return uncore_write_control_freq(data, value, index); 263 + 361 264 default: 362 265 break; 363 266 } ··· 442 291 return -EINVAL; 443 292 444 293 /* Register callbacks to uncore core */ 445 - ret = uncore_freq_common_init(uncore_read, uncore_write_control_freq); 294 + ret = uncore_freq_common_init(uncore_read, uncore_write); 446 295 if (ret) 447 296 return ret; 448 297 ··· 559 408 cluster_info->uncore_data.cluster_id = j; 560 409 561 410 cluster_info->uncore_root = tpmi_uncore; 411 + 412 + if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) >= UNCORE_ELC_SUPPORTED_VERSION) 413 + cluster_info->elc_supported = true; 562 414 563 415 ret = uncore_freq_add_entry(&cluster_info->uncore_data, 0); 564 416 if (ret) {