@@ -373,7 +373,7 @@ static int iter_perf_levels_update_state(struct scmi_iterator_state *st,
373
373
return 0 ;
374
374
}
375
375
376
- static inline void
376
+ static inline int
377
377
process_response_opp (struct device * dev , struct perf_dom_info * dom ,
378
378
struct scmi_opp * opp , unsigned int loop_idx ,
379
379
const struct scmi_msg_resp_perf_describe_levels * r )
@@ -386,12 +386,16 @@ process_response_opp(struct device *dev, struct perf_dom_info *dom,
386
386
le16_to_cpu (r -> opp [loop_idx ].transition_latency_us );
387
387
388
388
ret = xa_insert (& dom -> opps_by_lvl , opp -> perf , opp , GFP_KERNEL );
389
- if (ret )
389
+ if (ret ) {
390
390
dev_warn (dev , "Failed to add opps_by_lvl at %d for %s - ret:%d\n" ,
391
391
opp -> perf , dom -> info .name , ret );
392
+ return ret ;
393
+ }
394
+
395
+ return 0 ;
392
396
}
393
397
394
- static inline void
398
+ static inline int
395
399
process_response_opp_v4 (struct device * dev , struct perf_dom_info * dom ,
396
400
struct scmi_opp * opp , unsigned int loop_idx ,
397
401
const struct scmi_msg_resp_perf_describe_levels_v4 * r )
@@ -404,9 +408,11 @@ process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
404
408
le16_to_cpu (r -> opp [loop_idx ].transition_latency_us );
405
409
406
410
ret = xa_insert (& dom -> opps_by_lvl , opp -> perf , opp , GFP_KERNEL );
407
- if (ret )
411
+ if (ret ) {
408
412
dev_warn (dev , "Failed to add opps_by_lvl at %d for %s - ret:%d\n" ,
409
413
opp -> perf , dom -> info .name , ret );
414
+ return ret ;
415
+ }
410
416
411
417
/* Note that PERF v4 reports always five 32-bit words */
412
418
opp -> indicative_freq = le32_to_cpu (r -> opp [loop_idx ].indicative_freq );
@@ -415,30 +421,44 @@ process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
415
421
416
422
ret = xa_insert (& dom -> opps_by_idx , opp -> level_index , opp ,
417
423
GFP_KERNEL );
418
- if (ret )
424
+ if (ret ) {
419
425
dev_warn (dev ,
420
426
"Failed to add opps_by_idx at %d for %s - ret:%d\n" ,
421
427
opp -> level_index , dom -> info .name , ret );
422
428
429
+ /* Cleanup by_lvl too */
430
+ xa_erase (& dom -> opps_by_lvl , opp -> perf );
431
+
432
+ return ret ;
433
+ }
434
+
423
435
hash_add (dom -> opps_by_freq , & opp -> hash , opp -> indicative_freq );
424
436
}
437
+
438
+ return 0 ;
425
439
}
426
440
427
441
static int
428
442
iter_perf_levels_process_response (const struct scmi_protocol_handle * ph ,
429
443
const void * response ,
430
444
struct scmi_iterator_state * st , void * priv )
431
445
{
446
+ int ret ;
432
447
struct scmi_opp * opp ;
433
448
struct scmi_perf_ipriv * p = priv ;
434
449
435
- opp = & p -> perf_dom -> opp [st -> desc_index + st -> loop_idx ];
450
+ opp = & p -> perf_dom -> opp [p -> perf_dom -> opp_count ];
436
451
if (PROTOCOL_REV_MAJOR (p -> version ) <= 0x3 )
437
- process_response_opp (ph -> dev , p -> perf_dom , opp , st -> loop_idx ,
438
- response );
452
+ ret = process_response_opp (ph -> dev , p -> perf_dom , opp ,
453
+ st -> loop_idx , response );
439
454
else
440
- process_response_opp_v4 (ph -> dev , p -> perf_dom , opp , st -> loop_idx ,
441
- response );
455
+ ret = process_response_opp_v4 (ph -> dev , p -> perf_dom , opp ,
456
+ st -> loop_idx , response );
457
+
458
+ /* Skip BAD duplicates received from firmware */
459
+ if (ret )
460
+ return ret == - EBUSY ? 0 : ret ;
461
+
442
462
p -> perf_dom -> opp_count ++ ;
443
463
444
464
dev_dbg (ph -> dev , "Level %d Power %d Latency %dus Ifreq %d Index %d\n" ,
0 commit comments