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

hwmon: (amd_energy) Improve the accumulation logic

Factor out the common code in the accumulation functions for core and
socket accumulation.

While at it, handle the return value of the amd_create_sensor() function.

Signed-off-by: Naveen Krishna Chatradhi <nchatrad@amd.com>
Link: https://lore.kernel.org/r/20200929105322.8919-4-nchatrad@amd.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Naveen Krishna Chatradhi and committed by
Guenter Roeck
b75394c1 514db2b4

+45 -84
+45 -84
drivers/hwmon/amd_energy.c
··· 74 74 data->energy_units = (rapl_units & AMD_ENERGY_UNIT_MASK) >> 8; 75 75 } 76 76 77 - static void accumulate_socket_delta(struct amd_energy_data *data, 78 - int sock, int cpu) 77 + static void accumulate_delta(struct amd_energy_data *data, 78 + int channel, int cpu, u32 reg) 79 79 { 80 - struct sensor_accumulator *s_accum; 80 + struct sensor_accumulator *accum; 81 81 u64 input; 82 82 83 83 mutex_lock(&data->lock); 84 - rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input); 84 + rdmsrl_safe_on_cpu(cpu, reg, &input); 85 85 input &= AMD_ENERGY_MASK; 86 86 87 - s_accum = &data->accums[data->nr_cpus + sock]; 88 - if (input >= s_accum->prev_value) 89 - s_accum->energy_ctr += 90 - input - s_accum->prev_value; 87 + accum = &data->accums[channel]; 88 + if (input >= accum->prev_value) 89 + accum->energy_ctr += 90 + input - accum->prev_value; 91 91 else 92 - s_accum->energy_ctr += UINT_MAX - 93 - s_accum->prev_value + input; 92 + accum->energy_ctr += UINT_MAX - 93 + accum->prev_value + input; 94 94 95 - s_accum->prev_value = input; 96 - mutex_unlock(&data->lock); 97 - } 98 - 99 - static void accumulate_core_delta(struct amd_energy_data *data) 100 - { 101 - struct sensor_accumulator *c_accum; 102 - u64 input; 103 - int cpu; 104 - 105 - mutex_lock(&data->lock); 106 - if (data->core_id >= data->nr_cpus) 107 - data->core_id = 0; 108 - 109 - cpu = data->core_id; 110 - 111 - if (!cpu_online(cpu)) 112 - goto out; 113 - 114 - rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input); 115 - input &= AMD_ENERGY_MASK; 116 - 117 - c_accum = &data->accums[cpu]; 118 - 119 - if (input >= c_accum->prev_value) 120 - c_accum->energy_ctr += 121 - input - c_accum->prev_value; 122 - else 123 - c_accum->energy_ctr += UINT_MAX - 124 - c_accum->prev_value + input; 125 - 126 - c_accum->prev_value = input; 127 - 128 - out: 129 - data->core_id++; 95 + accum->prev_value = input; 130 96 mutex_unlock(&data->lock); 131 97 } 132 98 133 99 static void read_accumulate(struct amd_energy_data *data) 134 100 { 135 - int sock; 101 + int sock, scpu, cpu; 136 102 137 103 for (sock = 0; sock < data->nr_socks; sock++) { 138 - int cpu; 104 + scpu = cpumask_first_and(cpu_online_mask, 105 + cpumask_of_node(sock)); 139 106 140 - cpu = cpumask_first_and(cpu_online_mask, 141 - cpumask_of_node(sock)); 142 - 143 - accumulate_socket_delta(data, sock, cpu); 107 + accumulate_delta(data, data->nr_cpus + sock, 108 + scpu, ENERGY_PKG_MSR); 144 109 } 145 110 146 - accumulate_core_delta(data); 111 + if (data->core_id >= data->nr_cpus) 112 + data->core_id = 0; 113 + 114 + cpu = data->core_id; 115 + if (cpu_online(cpu)) 116 + accumulate_delta(data, cpu, cpu, ENERGY_CORE_MSR); 117 + 118 + data->core_id++; 147 119 } 148 120 149 121 static void amd_add_delta(struct amd_energy_data *data, int ch, 150 - int cpu, long *val, bool is_core) 122 + int cpu, long *val, u32 reg) 151 123 { 152 - struct sensor_accumulator *s_accum, *c_accum; 124 + struct sensor_accumulator *accum; 153 125 u64 input; 154 126 155 127 mutex_lock(&data->lock); 156 - if (!is_core) { 157 - rdmsrl_safe_on_cpu(cpu, ENERGY_PKG_MSR, &input); 158 - input &= AMD_ENERGY_MASK; 128 + rdmsrl_safe_on_cpu(cpu, reg, &input); 129 + input &= AMD_ENERGY_MASK; 159 130 160 - s_accum = &data->accums[ch]; 161 - if (input >= s_accum->prev_value) 162 - input += s_accum->energy_ctr - 163 - s_accum->prev_value; 164 - else 165 - input += UINT_MAX - s_accum->prev_value + 166 - s_accum->energy_ctr; 167 - } else { 168 - rdmsrl_safe_on_cpu(cpu, ENERGY_CORE_MSR, &input); 169 - input &= AMD_ENERGY_MASK; 170 - 171 - c_accum = &data->accums[ch]; 172 - if (input >= c_accum->prev_value) 173 - input += c_accum->energy_ctr - 174 - c_accum->prev_value; 175 - else 176 - input += UINT_MAX - c_accum->prev_value + 177 - c_accum->energy_ctr; 178 - } 131 + accum = &data->accums[ch]; 132 + if (input >= accum->prev_value) 133 + input += accum->energy_ctr - 134 + accum->prev_value; 135 + else 136 + input += UINT_MAX - accum->prev_value + 137 + accum->energy_ctr; 179 138 180 139 /* Energy consumed = (1/(2^ESU) * RAW * 1000000UL) μJoules */ 181 140 *val = div64_ul(input * 1000000UL, BIT(data->energy_units)); ··· 147 188 u32 attr, int channel, long *val) 148 189 { 149 190 struct amd_energy_data *data = dev_get_drvdata(dev); 191 + u32 reg; 150 192 int cpu; 151 193 152 194 if (channel >= data->nr_cpus) { 153 195 cpu = cpumask_first_and(cpu_online_mask, 154 196 cpumask_of_node 155 197 (channel - data->nr_cpus)); 156 - amd_add_delta(data, channel, cpu, val, false); 198 + reg = ENERGY_PKG_MSR; 157 199 } else { 158 200 cpu = channel; 159 201 if (!cpu_online(cpu)) 160 202 return -ENODEV; 161 203 162 - amd_add_delta(data, channel, cpu, val, true); 204 + reg = ENERGY_CORE_MSR; 163 205 } 206 + amd_add_delta(data, channel, cpu, val, reg); 164 207 165 208 return 0; 166 209 } ··· 203 242 204 243 static int amd_create_sensor(struct device *dev, 205 244 struct amd_energy_data *data, 206 - u8 type, u32 config) 245 + enum hwmon_sensor_types type, u32 config) 207 246 { 208 247 struct hwmon_channel_info *info = &data->energy_info; 209 248 struct sensor_accumulator *accums; ··· 262 301 struct device *hwmon_dev; 263 302 struct amd_energy_data *data; 264 303 struct device *dev = &pdev->dev; 304 + int ret; 265 305 266 306 data = devm_kzalloc(dev, 267 307 sizeof(struct amd_energy_data), GFP_KERNEL); ··· 275 313 dev_set_drvdata(dev, data); 276 314 /* Populate per-core energy reporting */ 277 315 data->info[0] = &data->energy_info; 278 - amd_create_sensor(dev, data, hwmon_energy, 279 - HWMON_E_INPUT | HWMON_E_LABEL); 316 + ret = amd_create_sensor(dev, data, hwmon_energy, 317 + HWMON_E_INPUT | HWMON_E_LABEL); 318 + if (ret) 319 + return ret; 280 320 281 321 mutex_init(&data->lock); 282 322 get_energy_units(data); ··· 299 335 300 336 data->wrap_accumulate = kthread_run(energy_accumulator, data, 301 337 "%s", dev_name(hwmon_dev)); 302 - if (IS_ERR(data->wrap_accumulate)) 303 - return PTR_ERR(data->wrap_accumulate); 304 - 305 338 return PTR_ERR_OR_ZERO(data->wrap_accumulate); 306 339 } 307 340