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.

iio: gts: Simplify available scale table build

Make available scale building more clear. This hurts the performance
quite a bit by looping throgh the scales many times instead of doing
everything in one loop. It however simplifies logic by:
- decoupling the gain and scale allocations & computations
- keeping the temporary 'per_time_gains' table inside the
per_time_scales computation function.
- separating building the 'all scales' table in own function and doing
it based on the already computed per-time scales.

Signed-off-by: Matti Vaittinen <mazziesaccount@gmail.com>
Tested-by: subhajit.ghosh@tweaklogic.com
Link: https://patch.msgid.link/Z1_rRXqdhxhL6wBw@mva-rohm
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Matti Vaittinen and committed by
Jonathan Cameron
32f80e20 6eaf49f1

+179 -103
+179 -103
drivers/iio/industrialio-gts-helper.c
··· 160 160 gts->num_avail_all_scales = 0; 161 161 } 162 162 163 + static int scale_eq(int *sc1, int *sc2) 164 + { 165 + return sc1[0] == sc2[0] && sc1[1] == sc2[1]; 166 + } 167 + 168 + static int scale_smaller(int *sc1, int *sc2) 169 + { 170 + if (sc1[0] != sc2[0]) 171 + return sc1[0] < sc2[0]; 172 + 173 + /* If integer parts are equal, fixp parts */ 174 + return sc1[1] < sc2[1]; 175 + } 176 + 177 + /* 178 + * Do a single table listing all the unique scales that any combination of 179 + * supported gains and times can provide. 180 + */ 181 + static int do_combined_scaletable(struct iio_gts *gts, 182 + size_t all_scales_tbl_bytes) 183 + { 184 + int t_idx, i, new_idx; 185 + int **scales = gts->per_time_avail_scale_tables; 186 + int *all_scales = kcalloc(gts->num_itime, all_scales_tbl_bytes, 187 + GFP_KERNEL); 188 + 189 + if (!all_scales) 190 + return -ENOMEM; 191 + /* 192 + * Create table containing all of the supported scales by looping 193 + * through all of the per-time scales and copying the unique scales 194 + * into one sorted table. 195 + * 196 + * We assume all the gains for same integration time were unique. 197 + * It is likely the first time table had greatest time multiplier as 198 + * the times are in the order of preference and greater times are 199 + * usually preferred. Hence we start from the last table which is likely 200 + * to have the smallest total gains. 201 + */ 202 + t_idx = gts->num_itime - 1; 203 + memcpy(all_scales, scales[t_idx], all_scales_tbl_bytes); 204 + new_idx = gts->num_hwgain * 2; 205 + 206 + while (t_idx-- > 0) { 207 + for (i = 0; i < gts->num_hwgain ; i++) { 208 + int *candidate = &scales[t_idx][i * 2]; 209 + int chk; 210 + 211 + if (scale_smaller(candidate, &all_scales[new_idx - 2])) { 212 + all_scales[new_idx] = candidate[0]; 213 + all_scales[new_idx + 1] = candidate[1]; 214 + new_idx += 2; 215 + 216 + continue; 217 + } 218 + for (chk = 0; chk < new_idx; chk += 2) 219 + if (!scale_smaller(candidate, &all_scales[chk])) 220 + break; 221 + 222 + if (scale_eq(candidate, &all_scales[chk])) 223 + continue; 224 + 225 + memmove(&all_scales[chk + 2], &all_scales[chk], 226 + (new_idx - chk) * sizeof(int)); 227 + all_scales[chk] = candidate[0]; 228 + all_scales[chk + 1] = candidate[1]; 229 + new_idx += 2; 230 + } 231 + } 232 + 233 + gts->num_avail_all_scales = new_idx / 2; 234 + gts->avail_all_scales_table = all_scales; 235 + 236 + return 0; 237 + } 238 + 239 + static void iio_gts_free_int_table_array(int **arr, int num_tables) 240 + { 241 + int i; 242 + 243 + for (i = 0; i < num_tables; i++) 244 + kfree(arr[i]); 245 + 246 + kfree(arr); 247 + } 248 + 249 + static int iio_gts_alloc_int_table_array(int ***arr, int num_tables, int num_table_items) 250 + { 251 + int i, **tmp; 252 + 253 + tmp = kcalloc(num_tables, sizeof(**arr), GFP_KERNEL); 254 + if (!tmp) 255 + return -ENOMEM; 256 + 257 + for (i = 0; i < num_tables; i++) { 258 + tmp[i] = kcalloc(num_table_items, sizeof(int), GFP_KERNEL); 259 + if (!tmp[i]) 260 + goto err_free; 261 + } 262 + 263 + *arr = tmp; 264 + 265 + return 0; 266 + err_free: 267 + iio_gts_free_int_table_array(tmp, i); 268 + 269 + return -ENOMEM; 270 + } 271 + 163 272 static int iio_gts_gain_cmp(const void *a, const void *b) 164 273 { 165 274 return *(int *)a - *(int *)b; 166 275 } 167 276 168 - static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales) 277 + static int fill_and_sort_scaletables(struct iio_gts *gts, int **gains, int **scales) 169 278 { 170 - int i, j, new_idx, time_idx, ret = 0; 171 - int *all_gains; 172 - size_t gain_bytes; 279 + int i, j, ret; 173 280 174 281 for (i = 0; i < gts->num_itime; i++) { 175 282 /* ··· 296 189 } 297 190 } 298 191 299 - gain_bytes = array_size(gts->num_hwgain, sizeof(int)); 300 - all_gains = kcalloc(gts->num_itime, gain_bytes, GFP_KERNEL); 301 - if (!all_gains) 302 - return -ENOMEM; 192 + return 0; 193 + } 194 + 195 + static void compute_per_time_gains(struct iio_gts *gts, int **gains) 196 + { 197 + int i, j; 198 + 199 + for (i = 0; i < gts->num_itime; i++) { 200 + for (j = 0; j < gts->num_hwgain; j++) 201 + gains[i][j] = gts->hwgain_table[j].gain * 202 + gts->itime_table[i].mul; 203 + } 204 + } 205 + 206 + static int compute_per_time_tables(struct iio_gts *gts, int **scales) 207 + { 208 + int **per_time_gains; 209 + int ret; 303 210 304 211 /* 305 - * We assume all the gains for same integration time were unique. 306 - * It is likely the first time table had greatest time multiplier as 307 - * the times are in the order of preference and greater times are 308 - * usually preferred. Hence we start from the last table which is likely 309 - * to have the smallest total gains. 212 + * Create a temporary array of the 'total gains' for each integration 213 + * time. 310 214 */ 311 - time_idx = gts->num_itime - 1; 312 - memcpy(all_gains, gains[time_idx], gain_bytes); 313 - new_idx = gts->num_hwgain; 215 + ret = iio_gts_alloc_int_table_array(&per_time_gains, gts->num_itime, 216 + gts->num_hwgain); 217 + if (ret) 218 + return ret; 314 219 315 - while (time_idx-- > 0) { 316 - for (j = 0; j < gts->num_hwgain; j++) { 317 - int candidate = gains[time_idx][j]; 318 - int chk; 220 + compute_per_time_gains(gts, per_time_gains); 319 221 320 - if (candidate > all_gains[new_idx - 1]) { 321 - all_gains[new_idx] = candidate; 322 - new_idx++; 222 + /* Convert the gains to scales and populate the scale tables */ 223 + ret = fill_and_sort_scaletables(gts, per_time_gains, scales); 323 224 324 - continue; 325 - } 326 - for (chk = 0; chk < new_idx; chk++) 327 - if (candidate <= all_gains[chk]) 328 - break; 329 - 330 - if (candidate == all_gains[chk]) 331 - continue; 332 - 333 - memmove(&all_gains[chk + 1], &all_gains[chk], 334 - (new_idx - chk) * sizeof(int)); 335 - all_gains[chk] = candidate; 336 - new_idx++; 337 - } 338 - } 339 - 340 - gts->avail_all_scales_table = kcalloc(new_idx, 2 * sizeof(int), 341 - GFP_KERNEL); 342 - if (!gts->avail_all_scales_table) { 343 - ret = -ENOMEM; 344 - goto free_out; 345 - } 346 - gts->num_avail_all_scales = new_idx; 347 - 348 - for (i = 0; i < gts->num_avail_all_scales; i++) { 349 - ret = iio_gts_total_gain_to_scale(gts, all_gains[i], 350 - &gts->avail_all_scales_table[i * 2], 351 - &gts->avail_all_scales_table[i * 2 + 1]); 352 - 353 - if (ret) { 354 - kfree(gts->avail_all_scales_table); 355 - gts->num_avail_all_scales = 0; 356 - goto free_out; 357 - } 358 - } 359 - 360 - free_out: 361 - kfree(all_gains); 225 + iio_gts_free_int_table_array(per_time_gains, gts->num_itime); 362 226 363 227 return ret; 228 + } 229 + 230 + /* 231 + * Create a table of supported scales for each supported integration time. 232 + * This can be used as available_scales by drivers which don't allow scale 233 + * setting to change the integration time to display correct set of scales 234 + * depending on the used integration time. 235 + */ 236 + static int **create_per_time_scales(struct iio_gts *gts) 237 + { 238 + int **per_time_scales, ret; 239 + 240 + ret = iio_gts_alloc_int_table_array(&per_time_scales, gts->num_itime, 241 + gts->num_hwgain * 2); 242 + if (ret) 243 + return ERR_PTR(ret); 244 + 245 + ret = compute_per_time_tables(gts, per_time_scales); 246 + if (ret) 247 + goto err_out; 248 + 249 + return per_time_scales; 250 + 251 + err_out: 252 + iio_gts_free_int_table_array(per_time_scales, gts->num_itime); 253 + 254 + return ERR_PTR(ret); 364 255 } 365 256 366 257 /** ··· 380 275 */ 381 276 static int iio_gts_build_avail_scale_table(struct iio_gts *gts) 382 277 { 383 - int **per_time_gains, **per_time_scales, i, j, ret = -ENOMEM; 278 + int ret, all_scales_tbl_bytes; 279 + int **per_time_scales; 384 280 385 - per_time_gains = kcalloc(gts->num_itime, sizeof(*per_time_gains), GFP_KERNEL); 386 - if (!per_time_gains) 387 - return ret; 281 + if (unlikely(check_mul_overflow(gts->num_hwgain, 2 * sizeof(int), 282 + &all_scales_tbl_bytes))) 283 + return -EOVERFLOW; 388 284 389 - per_time_scales = kcalloc(gts->num_itime, sizeof(*per_time_scales), GFP_KERNEL); 390 - if (!per_time_scales) 391 - goto free_gains; 285 + per_time_scales = create_per_time_scales(gts); 286 + if (IS_ERR(per_time_scales)) 287 + return PTR_ERR(per_time_scales); 392 288 393 - for (i = 0; i < gts->num_itime; i++) { 394 - per_time_scales[i] = kcalloc(gts->num_hwgain, 2 * sizeof(int), 395 - GFP_KERNEL); 396 - if (!per_time_scales[i]) 397 - goto err_free_out; 398 - 399 - per_time_gains[i] = kcalloc(gts->num_hwgain, sizeof(int), 400 - GFP_KERNEL); 401 - if (!per_time_gains[i]) { 402 - kfree(per_time_scales[i]); 403 - goto err_free_out; 404 - } 405 - 406 - for (j = 0; j < gts->num_hwgain; j++) 407 - per_time_gains[i][j] = gts->hwgain_table[j].gain * 408 - gts->itime_table[i].mul; 409 - } 410 - 411 - ret = gain_to_scaletables(gts, per_time_gains, per_time_scales); 412 - if (ret) 413 - goto err_free_out; 414 - 415 - for (i = 0; i < gts->num_itime; i++) 416 - kfree(per_time_gains[i]); 417 - kfree(per_time_gains); 418 289 gts->per_time_avail_scale_tables = per_time_scales; 419 290 420 - return 0; 421 - 422 - err_free_out: 423 - for (i--; i >= 0; i--) { 424 - kfree(per_time_scales[i]); 425 - kfree(per_time_gains[i]); 291 + ret = do_combined_scaletable(gts, all_scales_tbl_bytes); 292 + if (ret) { 293 + iio_gts_free_int_table_array(per_time_scales, gts->num_itime); 294 + return ret; 426 295 } 427 - kfree(per_time_scales); 428 - free_gains: 429 - kfree(per_time_gains); 430 296 431 - return ret; 297 + return 0; 432 298 } 433 299 434 300 static void iio_gts_us_to_int_micro(int *time_us, int *int_micro_times,