Skip to content

Commit 754f04c

Browse files
cris-masudeep-holla
authored andcommitted
firmware: arm_scmi: Relax CLOCK_DESCRIBE_RATES out-of-spec checks
A reply to CLOCK_DESCRIBE_RATES issued against a non rate-discrete clock should be composed of a triplet of rates descriptors (min/max/step) returned all in one reply message. This is not always the case when dealing with some SCMI server deployed in the wild: relax such constraint while maintaining memory safety by checking carefully the returned payload size. While at that cleanup a stale debug printout. Link: https://lore.kernel.org/r/[email protected] Fixes: 7bc7caa ("firmware: arm_scmi: Use common iterators in the clock protocol") Tested-by: Robin Murphy <[email protected]> Signed-off-by: Cristian Marussi <[email protected]> Signed-off-by: Sudeep Holla <[email protected]>
1 parent 44dbdf3 commit 754f04c

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

drivers/firmware/arm_scmi/clock.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
194194
}
195195

196196
struct scmi_clk_ipriv {
197+
struct device *dev;
197198
u32 clk_id;
198199
struct scmi_clock_info *clk;
199200
};
@@ -223,6 +224,29 @@ iter_clk_describe_update_state(struct scmi_iterator_state *st,
223224
st->num_returned = NUM_RETURNED(flags);
224225
p->clk->rate_discrete = RATE_DISCRETE(flags);
225226

227+
/* Warn about out of spec replies ... */
228+
if (!p->clk->rate_discrete &&
229+
(st->num_returned != 3 || st->num_remaining != 0)) {
230+
dev_warn(p->dev,
231+
"Out-of-spec CLOCK_DESCRIBE_RATES reply for %s - returned:%d remaining:%d rx_len:%zd\n",
232+
p->clk->name, st->num_returned, st->num_remaining,
233+
st->rx_len);
234+
235+
/*
236+
* A known quirk: a triplet is returned but num_returned != 3
237+
* Check for a safe payload size and fix.
238+
*/
239+
if (st->num_returned != 3 && st->num_remaining == 0 &&
240+
st->rx_len == sizeof(*r) + sizeof(__le32) * 2 * 3) {
241+
st->num_returned = 3;
242+
st->num_remaining = 0;
243+
} else {
244+
dev_err(p->dev,
245+
"Cannot fix out-of-spec reply !\n");
246+
return -EPROTO;
247+
}
248+
}
249+
226250
return 0;
227251
}
228252

@@ -255,7 +279,6 @@ iter_clk_describe_process_response(const struct scmi_protocol_handle *ph,
255279

256280
*rate = RATE_TO_U64(r->rate[st->loop_idx]);
257281
p->clk->list.num_rates++;
258-
//XXX dev_dbg(ph->dev, "Rate %llu Hz\n", *rate);
259282
}
260283

261284
return ret;
@@ -275,6 +298,7 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
275298
struct scmi_clk_ipriv cpriv = {
276299
.clk_id = clk_id,
277300
.clk = clk,
301+
.dev = ph->dev,
278302
};
279303

280304
iter = ph->hops->iter_response_init(ph, &ops, SCMI_MAX_NUM_RATES,

drivers/firmware/arm_scmi/driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ static int scmi_iterator_run(void *iter)
12231223
if (ret)
12241224
break;
12251225

1226+
st->rx_len = i->t->rx.len;
12261227
ret = iops->update_state(st, i->resp, i->priv);
12271228
if (ret)
12281229
break;

drivers/firmware/arm_scmi/protocols.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ struct scmi_protocol_handle {
179179
* @max_resources: Maximum acceptable number of items, configured by the caller
180180
* depending on the underlying resources that it is querying.
181181
* @loop_idx: The iterator loop index in the current multi-part reply.
182+
* @rx_len: Size in bytes of the currenly processed message; it can be used by
183+
* the user of the iterator to verify a reply size.
182184
* @priv: Optional pointer to some additional state-related private data setup
183185
* by the caller during the iterations.
184186
*/
@@ -188,6 +190,7 @@ struct scmi_iterator_state {
188190
unsigned int num_remaining;
189191
unsigned int max_resources;
190192
unsigned int loop_idx;
193+
size_t rx_len;
191194
void *priv;
192195
};
193196

0 commit comments

Comments
 (0)