@@ -160,16 +160,123 @@ static void iio_gts_purge_avail_scale_table(struct iio_gts *gts)
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
/*
@@ -189,71 +296,69 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
189
296
}
190
297
}
191
298
192
- gain_bytes = array_size (gts -> num_hwgain , sizeof (int ));
193
- all_gains = kcalloc (gts -> num_itime , gain_bytes , GFP_KERNEL );
194
- if (!all_gains )
195
- return - ENOMEM ;
299
+ return 0 ;
300
+ }
301
+
302
+ static void compute_per_time_gains (struct iio_gts * gts , int * * gains )
303
+ {
304
+ int i , j ;
305
+
306
+ for (i = 0 ; i < gts -> num_itime ; i ++ ) {
307
+ for (j = 0 ; j < gts -> num_hwgain ; j ++ )
308
+ gains [i ][j ] = gts -> hwgain_table [j ].gain *
309
+ gts -> itime_table [i ].mul ;
310
+ }
311
+ }
312
+
313
+ static int compute_per_time_tables (struct iio_gts * gts , int * * scales )
314
+ {
315
+ int * * per_time_gains ;
316
+ int ret ;
196
317
197
318
/*
198
- * We assume all the gains for same integration time were unique.
199
- * It is likely the first time table had greatest time multiplier as
200
- * the times are in the order of preference and greater times are
201
- * usually preferred. Hence we start from the last table which is likely
202
- * to have the smallest total gains.
319
+ * Create a temporary array of the 'total gains' for each integration
320
+ * time.
203
321
*/
204
- time_idx = gts -> num_itime - 1 ;
205
- memcpy (all_gains , gains [time_idx ], gain_bytes );
206
- new_idx = gts -> num_hwgain ;
322
+ ret = iio_gts_alloc_int_table_array (& per_time_gains , gts -> num_itime ,
323
+ gts -> num_hwgain );
324
+ if (ret )
325
+ return ret ;
207
326
208
- while (time_idx -- > 0 ) {
209
- for (j = 0 ; j < gts -> num_hwgain ; j ++ ) {
210
- int candidate = gains [time_idx ][j ];
211
- int chk ;
327
+ compute_per_time_gains (gts , per_time_gains );
212
328
213
- if (candidate > all_gains [new_idx - 1 ]) {
214
- all_gains [new_idx ] = candidate ;
215
- new_idx ++ ;
329
+ /* Convert the gains to scales and populate the scale tables */
330
+ ret = fill_and_sort_scaletables (gts , per_time_gains , scales );
216
331
217
- continue ;
218
- }
219
- for (chk = 0 ; chk < new_idx ; chk ++ )
220
- if (candidate <= all_gains [chk ])
221
- break ;
332
+ iio_gts_free_int_table_array (per_time_gains , gts -> num_itime );
222
333
223
- if ( candidate == all_gains [ chk ])
224
- continue ;
334
+ return ret ;
335
+ }
225
336
226
- memmove (& all_gains [chk + 1 ], & all_gains [chk ],
227
- (new_idx - chk ) * sizeof (int ));
228
- all_gains [chk ] = candidate ;
229
- new_idx ++ ;
230
- }
231
- }
337
+ /*
338
+ * Create a table of supported scales for each supported integration time.
339
+ * This can be used as available_scales by drivers which don't allow scale
340
+ * setting to change the integration time to display correct set of scales
341
+ * depending on the used integration time.
342
+ */
343
+ static int * * create_per_time_scales (struct iio_gts * gts )
344
+ {
345
+ int * * per_time_scales , ret ;
232
346
233
- gts -> avail_all_scales_table = kcalloc (new_idx , 2 * sizeof (int ),
234
- GFP_KERNEL );
235
- if (!gts -> avail_all_scales_table ) {
236
- ret = - ENOMEM ;
237
- goto free_out ;
238
- }
239
- gts -> num_avail_all_scales = new_idx ;
347
+ ret = iio_gts_alloc_int_table_array (& per_time_scales , gts -> num_itime ,
348
+ gts -> num_hwgain * 2 );
349
+ if (ret )
350
+ return ERR_PTR (ret );
240
351
241
- for (i = 0 ; i < gts -> num_avail_all_scales ; i ++ ) {
242
- ret = iio_gts_total_gain_to_scale (gts , all_gains [i ],
243
- & gts -> avail_all_scales_table [i * 2 ],
244
- & gts -> avail_all_scales_table [i * 2 + 1 ]);
352
+ ret = compute_per_time_tables (gts , per_time_scales );
353
+ if (ret )
354
+ goto err_out ;
245
355
246
- if (ret ) {
247
- kfree (gts -> avail_all_scales_table );
248
- gts -> num_avail_all_scales = 0 ;
249
- goto free_out ;
250
- }
251
- }
356
+ return per_time_scales ;
252
357
253
- free_out :
254
- kfree ( all_gains );
358
+ err_out :
359
+ iio_gts_free_int_table_array ( per_time_scales , gts -> num_itime );
255
360
256
- return ret ;
361
+ return ERR_PTR ( ret ) ;
257
362
}
258
363
259
364
/**
@@ -275,55 +380,26 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
275
380
*/
276
381
static int iio_gts_build_avail_scale_table (struct iio_gts * gts )
277
382
{
278
- int * * per_time_gains , * * per_time_scales , i , j , ret = - ENOMEM ;
383
+ int ret , all_scales_tbl_bytes ;
384
+ int * * per_time_scales ;
279
385
280
- per_time_gains = kcalloc (gts -> num_itime , sizeof (* per_time_gains ), GFP_KERNEL );
281
- if (!per_time_gains )
282
- return ret ;
283
-
284
- per_time_scales = kcalloc (gts -> num_itime , sizeof (* per_time_scales ), GFP_KERNEL );
285
- if (!per_time_scales )
286
- goto free_gains ;
287
-
288
- for (i = 0 ; i < gts -> num_itime ; i ++ ) {
289
- per_time_scales [i ] = kcalloc (gts -> num_hwgain , 2 * sizeof (int ),
290
- GFP_KERNEL );
291
- if (!per_time_scales [i ])
292
- goto err_free_out ;
293
-
294
- per_time_gains [i ] = kcalloc (gts -> num_hwgain , sizeof (int ),
295
- GFP_KERNEL );
296
- if (!per_time_gains [i ]) {
297
- kfree (per_time_scales [i ]);
298
- goto err_free_out ;
299
- }
300
-
301
- for (j = 0 ; j < gts -> num_hwgain ; j ++ )
302
- per_time_gains [i ][j ] = gts -> hwgain_table [j ].gain *
303
- gts -> itime_table [i ].mul ;
304
- }
386
+ if (unlikely (check_mul_overflow (gts -> num_hwgain , 2 * sizeof (int ),
387
+ & all_scales_tbl_bytes )))
388
+ return - EOVERFLOW ;
305
389
306
- ret = gain_to_scaletables (gts , per_time_gains , per_time_scales );
307
- if (ret )
308
- goto err_free_out ;
390
+ per_time_scales = create_per_time_scales (gts );
391
+ if (IS_ERR ( per_time_scales ) )
392
+ return PTR_ERR ( per_time_scales ) ;
309
393
310
- for (i = 0 ; i < gts -> num_itime ; i ++ )
311
- kfree (per_time_gains [i ]);
312
- kfree (per_time_gains );
313
394
gts -> per_time_avail_scale_tables = per_time_scales ;
314
395
315
- return 0 ;
316
-
317
- err_free_out :
318
- for (i -- ; i >= 0 ; i -- ) {
319
- kfree (per_time_scales [i ]);
320
- kfree (per_time_gains [i ]);
396
+ ret = do_combined_scaletable (gts , all_scales_tbl_bytes );
397
+ if (ret ) {
398
+ iio_gts_free_int_table_array (per_time_scales , gts -> num_itime );
399
+ return ret ;
321
400
}
322
- kfree (per_time_scales );
323
- free_gains :
324
- kfree (per_time_gains );
325
401
326
- return ret ;
402
+ return 0 ;
327
403
}
328
404
329
405
static void iio_gts_us_to_int_micro (int * time_us , int * int_micro_times ,
0 commit comments