Skip to content

Commit 5d8a766

Browse files
cris-mastorulf
authored andcommitted
firmware: arm_scmi: Skip opp duplicates
Buggy firmware can reply with duplicated PERF opps descriptors. Ensure that the bad duplicates reported by the platform firmware doesn't get added to the opp-tables. Reported-by: Johan Hovold <[email protected]> Closes: https://lore.kernel.org/lkml/[email protected]/ Signed-off-by: Cristian Marussi <[email protected]> Tested-by: Johan Hovold <[email protected]> Reviewed-by: Sudeep Holla <[email protected]> Cc: [email protected] Message-ID: <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent f7c7c5a commit 5d8a766

File tree

1 file changed

+30
-10
lines changed
  • drivers/firmware/arm_scmi

1 file changed

+30
-10
lines changed

drivers/firmware/arm_scmi/perf.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ static int iter_perf_levels_update_state(struct scmi_iterator_state *st,
373373
return 0;
374374
}
375375

376-
static inline void
376+
static inline int
377377
process_response_opp(struct device *dev, struct perf_dom_info *dom,
378378
struct scmi_opp *opp, unsigned int loop_idx,
379379
const struct scmi_msg_resp_perf_describe_levels *r)
@@ -386,12 +386,16 @@ process_response_opp(struct device *dev, struct perf_dom_info *dom,
386386
le16_to_cpu(r->opp[loop_idx].transition_latency_us);
387387

388388
ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
389-
if (ret)
389+
if (ret) {
390390
dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
391391
opp->perf, dom->info.name, ret);
392+
return ret;
393+
}
394+
395+
return 0;
392396
}
393397

394-
static inline void
398+
static inline int
395399
process_response_opp_v4(struct device *dev, struct perf_dom_info *dom,
396400
struct scmi_opp *opp, unsigned int loop_idx,
397401
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,
404408
le16_to_cpu(r->opp[loop_idx].transition_latency_us);
405409

406410
ret = xa_insert(&dom->opps_by_lvl, opp->perf, opp, GFP_KERNEL);
407-
if (ret)
411+
if (ret) {
408412
dev_warn(dev, "Failed to add opps_by_lvl at %d for %s - ret:%d\n",
409413
opp->perf, dom->info.name, ret);
414+
return ret;
415+
}
410416

411417
/* Note that PERF v4 reports always five 32-bit words */
412418
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,
415421

416422
ret = xa_insert(&dom->opps_by_idx, opp->level_index, opp,
417423
GFP_KERNEL);
418-
if (ret)
424+
if (ret) {
419425
dev_warn(dev,
420426
"Failed to add opps_by_idx at %d for %s - ret:%d\n",
421427
opp->level_index, dom->info.name, ret);
422428

429+
/* Cleanup by_lvl too */
430+
xa_erase(&dom->opps_by_lvl, opp->perf);
431+
432+
return ret;
433+
}
434+
423435
hash_add(dom->opps_by_freq, &opp->hash, opp->indicative_freq);
424436
}
437+
438+
return 0;
425439
}
426440

427441
static int
428442
iter_perf_levels_process_response(const struct scmi_protocol_handle *ph,
429443
const void *response,
430444
struct scmi_iterator_state *st, void *priv)
431445
{
446+
int ret;
432447
struct scmi_opp *opp;
433448
struct scmi_perf_ipriv *p = priv;
434449

435-
opp = &p->perf_dom->opp[st->desc_index + st->loop_idx];
450+
opp = &p->perf_dom->opp[p->perf_dom->opp_count];
436451
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);
439454
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+
442462
p->perf_dom->opp_count++;
443463

444464
dev_dbg(ph->dev, "Level %d Power %d Latency %dus Ifreq %d Index %d\n",

0 commit comments

Comments
 (0)