Skip to content

Commit d95ce66

Browse files
committed
Merge tag 'scmi-fixes-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes
Arm SCMI firmware driver fixes for v5.19 Few more fixes to address: 1. Issue reported on Juno with HDLCD clock which turned out to be yet another firmware issue. The firmware is not conformant to the spec and we now have to workaround as this may be copied to other platforms as well. The spec expects to return size of 3 for a range clock rate description while the firmware returns 1. We have other ways to validate all the 3 entries the driver reads are polpulated and we use the same to workaround this firmware bug. 2. Optee transport not setting the correct reponse length which is similar to the one reported earlier on Rockchip platform. 3. Drop the usage of the deprecated ida_simple_{get,remove} and migrate to the ida_{alloc,free} * tag 'scmi-fixes-5.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux: firmware: arm_scmi: Remove usage of the deprecated ida_simple_xxx API firmware: arm_scmi: Fix response size warning for OPTEE transport firmware: arm_scmi: Relax CLOCK_DESCRIBE_RATES out-of-spec checks Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 1f66f63 + 4ce7e51 commit d95ce66

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

drivers/firmware/arm_scmi/bus.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
181181
return NULL;
182182
}
183183

184-
id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
184+
id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
185185
if (id < 0) {
186186
kfree_const(scmi_dev->name);
187187
kfree(scmi_dev);
@@ -204,15 +204,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
204204
put_dev:
205205
kfree_const(scmi_dev->name);
206206
put_device(&scmi_dev->dev);
207-
ida_simple_remove(&scmi_bus_id, id);
207+
ida_free(&scmi_bus_id, id);
208208
return NULL;
209209
}
210210

211211
void scmi_device_destroy(struct scmi_device *scmi_dev)
212212
{
213213
kfree_const(scmi_dev->name);
214214
scmi_handle_put(scmi_dev->handle);
215-
ida_simple_remove(&scmi_bus_id, scmi_dev->id);
215+
ida_free(&scmi_bus_id, scmi_dev->id);
216216
device_unregister(&scmi_dev->dev);
217217
}
218218

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/optee.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ struct scmi_optee_channel {
117117
u32 channel_id;
118118
u32 tee_session;
119119
u32 caps;
120+
u32 rx_len;
120121
struct mutex mu;
121122
struct scmi_chan_info *cinfo;
122123
union {
@@ -302,6 +303,9 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t
302303
return -EIO;
303304
}
304305

306+
/* Save response size */
307+
channel->rx_len = param[2].u.memref.size;
308+
305309
return 0;
306310
}
307311

@@ -353,6 +357,7 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch
353357
shbuf = tee_shm_get_va(channel->tee_shm, 0);
354358
memset(shbuf, 0, msg_size);
355359
channel->req.msg = shbuf;
360+
channel->rx_len = msg_size;
356361

357362
return 0;
358363
}
@@ -508,7 +513,7 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
508513
struct scmi_optee_channel *channel = cinfo->transport_info;
509514

510515
if (channel->tee_shm)
511-
msg_fetch_response(channel->req.msg, SCMI_OPTEE_MAX_MSG_SIZE, xfer);
516+
msg_fetch_response(channel->req.msg, channel->rx_len, xfer);
512517
else
513518
shmem_fetch_response(channel->req.shmem, xfer);
514519
}

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)