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}
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEunHlEgbzHrJD3ZPhAEG6vDF+4pgFAmK6/jsACgkQAEG6vDF+
 4phDrBAAqGFJUmb34QqfKBhc9JtPIUUNvdHaxTDXotiokcGQXXZ7Ckx+F5sRTcYE
 xgFijjc80Rl5YpwTCCoSK5Kp9zmAAGycaZjKpxoHyNoXmctewS71pzZix+JLzJgG
 YZnQdHhdeXntH/7cKeJzE08BqzJDKeh2e3tMi3uCfZi+Uj5X4qMBj547in30E0BX
 lDxviE85xnKQYEGP7nbTZGjMrLjqpjehfj6CQrN3TbtIoAcad7lCEXY5l0cE9PF+
 N4x7kEGnlzUbi1dtLiyVBYU9OkA0wo3m4KAnughipvzfUm5RXKRTacaVsOGB2Mm4
 fesGnlC812XPSEcMnqqaY/ruPnVbPE8RtXx2FV1xoVlAQuyQqc97cDr/s7INX8aG
 FaPUHXBH63rga0zD6I8xVJ7zbzYZdZfhFY3WSO9ntONZtcL9F5YSrokthmlV0mWq
 +mmqb1fbvkb6Ym+rCtVCrgmsqJTgMDNYspDPl79EuycmH/eh1KzSPRrlQckrSbgK
 2KkryADrmbD0d3nQLb/AgWyfSbXFF+fbEh3oZm1xhSCL+bE+8qjVsIOVTfnz6jo/
 OdensXXdF43OsDQPPNSHijPe0LYexpSR3hVHphywZ/+aNOJ6h9e98O6DH93mdMqQ
 gmSbw16afKZpmfwyn95k1O6sBXj+b428CIodPoWPHkTC4S0v6T4=
 =xRfp
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmK/WEgACgkQmmx57+YA
 GNnx9g/+O3D/doxMRf6l3jRzG65tHU7IDiMt0yiTq1MOxl8LNDPfN4bC33+ehrLz
 4QkHZOpN65wrWt4lRsK1wyUFLCNxFrUu0slOaX0YxikgUq+MSRjSl4mf9+WePGf7
 dm7p1CzAxD33iNz5FvdHqu29SQ+gWFkIX0f34+q8xDwd+YhlXYWDIgZinDjWJhvp
 nuBqJ6vjT3HkMqemKc2XE3HY38bGpT1GSdh7DUNtJxZUG5hMCw5+j8OSJI3GQiYh
 W0f8KvWVnFMXP953EwNjL6C5QTahm+CxPne04k0yuo9MdVGmr3tHkNy3PyTZKYqK
 b/GjaLvvtdj5+7GfgPWFCIP3gcHX7WoJWI07xqN5Xrj04CTW/6I3QnleVn5g24h2
 ao5h/fX+u6Zed+SPPiLfemrOQRZK/h31vok1Oh6l9UALqYjvmzaG6rsKDp6JXNB4
 1wzc/1Gy2RLaI4QZhM7ypCrBpbiHiA3utz8j7/42eO267yN3FhqMgeFsSrcdC3iE
 ubexX23Tbu6yK9BsL5QDjF8b18SHR4NKxofTKAayTa/CELTWmDQ8ZSpWGZ5h4MwF
 N/UhtCAXYOSYyZox31hzc47zc4iFq0StgMlElZpa76jb3zNqmctBnYTRjQOFEBIm
 0U5128TphuBZF+a08/T6nIEIHhY4T7EcnHo6A6vkVPwWTmEwsDY=
 =sgSb
 -----END PGP SIGNATURE-----

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/20220628133315.699803-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2022-07-01 22:25:43 +02:00
commit d95ce66d4c
5 changed files with 38 additions and 5 deletions

View file

@ -181,7 +181,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
return NULL;
}
id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
id = ida_alloc_min(&scmi_bus_id, 1, GFP_KERNEL);
if (id < 0) {
kfree_const(scmi_dev->name);
kfree(scmi_dev);
@ -204,7 +204,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol,
put_dev:
kfree_const(scmi_dev->name);
put_device(&scmi_dev->dev);
ida_simple_remove(&scmi_bus_id, id);
ida_free(&scmi_bus_id, id);
return NULL;
}
@ -212,7 +212,7 @@ void scmi_device_destroy(struct scmi_device *scmi_dev)
{
kfree_const(scmi_dev->name);
scmi_handle_put(scmi_dev->handle);
ida_simple_remove(&scmi_bus_id, scmi_dev->id);
ida_free(&scmi_bus_id, scmi_dev->id);
device_unregister(&scmi_dev->dev);
}

View file

@ -194,6 +194,7 @@ static int rate_cmp_func(const void *_r1, const void *_r2)
}
struct scmi_clk_ipriv {
struct device *dev;
u32 clk_id;
struct scmi_clock_info *clk;
};
@ -223,6 +224,29 @@ iter_clk_describe_update_state(struct scmi_iterator_state *st,
st->num_returned = NUM_RETURNED(flags);
p->clk->rate_discrete = RATE_DISCRETE(flags);
/* Warn about out of spec replies ... */
if (!p->clk->rate_discrete &&
(st->num_returned != 3 || st->num_remaining != 0)) {
dev_warn(p->dev,
"Out-of-spec CLOCK_DESCRIBE_RATES reply for %s - returned:%d remaining:%d rx_len:%zd\n",
p->clk->name, st->num_returned, st->num_remaining,
st->rx_len);
/*
* A known quirk: a triplet is returned but num_returned != 3
* Check for a safe payload size and fix.
*/
if (st->num_returned != 3 && st->num_remaining == 0 &&
st->rx_len == sizeof(*r) + sizeof(__le32) * 2 * 3) {
st->num_returned = 3;
st->num_remaining = 0;
} else {
dev_err(p->dev,
"Cannot fix out-of-spec reply !\n");
return -EPROTO;
}
}
return 0;
}
@ -255,7 +279,6 @@ iter_clk_describe_process_response(const struct scmi_protocol_handle *ph,
*rate = RATE_TO_U64(r->rate[st->loop_idx]);
p->clk->list.num_rates++;
//XXX dev_dbg(ph->dev, "Rate %llu Hz\n", *rate);
}
return ret;
@ -275,6 +298,7 @@ scmi_clock_describe_rates_get(const struct scmi_protocol_handle *ph, u32 clk_id,
struct scmi_clk_ipriv cpriv = {
.clk_id = clk_id,
.clk = clk,
.dev = ph->dev,
};
iter = ph->hops->iter_response_init(ph, &ops, SCMI_MAX_NUM_RATES,

View file

@ -1223,6 +1223,7 @@ static int scmi_iterator_run(void *iter)
if (ret)
break;
st->rx_len = i->t->rx.len;
ret = iops->update_state(st, i->resp, i->priv);
if (ret)
break;

View file

@ -117,6 +117,7 @@ struct scmi_optee_channel {
u32 channel_id;
u32 tee_session;
u32 caps;
u32 rx_len;
struct mutex mu;
struct scmi_chan_info *cinfo;
union {
@ -302,6 +303,9 @@ static int invoke_process_msg_channel(struct scmi_optee_channel *channel, size_t
return -EIO;
}
/* Save response size */
channel->rx_len = param[2].u.memref.size;
return 0;
}
@ -353,6 +357,7 @@ static int setup_dynamic_shmem(struct device *dev, struct scmi_optee_channel *ch
shbuf = tee_shm_get_va(channel->tee_shm, 0);
memset(shbuf, 0, msg_size);
channel->req.msg = shbuf;
channel->rx_len = msg_size;
return 0;
}
@ -508,7 +513,7 @@ static void scmi_optee_fetch_response(struct scmi_chan_info *cinfo,
struct scmi_optee_channel *channel = cinfo->transport_info;
if (channel->tee_shm)
msg_fetch_response(channel->req.msg, SCMI_OPTEE_MAX_MSG_SIZE, xfer);
msg_fetch_response(channel->req.msg, channel->rx_len, xfer);
else
shmem_fetch_response(channel->req.shmem, xfer);
}

View file

@ -179,6 +179,8 @@ struct scmi_protocol_handle {
* @max_resources: Maximum acceptable number of items, configured by the caller
* depending on the underlying resources that it is querying.
* @loop_idx: The iterator loop index in the current multi-part reply.
* @rx_len: Size in bytes of the currenly processed message; it can be used by
* the user of the iterator to verify a reply size.
* @priv: Optional pointer to some additional state-related private data setup
* by the caller during the iterations.
*/
@ -188,6 +190,7 @@ struct scmi_iterator_state {
unsigned int num_remaining;
unsigned int max_resources;
unsigned int loop_idx;
size_t rx_len;
void *priv;
};