Commit d4f1920d authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'scmi-fixes-6.0' of...

Merge tag 'scmi-fixes-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/fixes

Arm SCMI fixes for v6.0

Few fixes addressing possible out of bound access violations by
hardening them, incorrect asynchronous resets by restricting them,
incorrect SCMI tracing message format by harmonizing them, missing
kernel-doc in optee transport, missing SCMI PM driver remove
routine by adding it to avoid warning when scmi driver is unloaded
and finally improve checks in the info_get operations.

* tag 'scmi-fixes-6.0' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scmi: Harmonize SCMI tracing message format
  firmware: arm_scmi: Add SCMI PM driver remove routine
  firmware: arm_scmi: Fix the asynchronous reset requests
  firmware: arm_scmi: Harden accesses to the reset domains
  firmware: arm_scmi: Harden accesses to the sensor domains
  firmware: arm_scmi: Improve checks in the info_get operations
  firmware: arm_scmi: Fix missing kernel-doc in optee

Link: https://lore.kernel.org/r/20220829174435.207911-1-sudeep.holla@arm.comSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 12f09234 40d30cf6
......@@ -450,9 +450,13 @@ static int scmi_clock_count_get(const struct scmi_protocol_handle *ph)
static const struct scmi_clock_info *
scmi_clock_info_get(const struct scmi_protocol_handle *ph, u32 clk_id)
{
struct scmi_clock_info *clk;
struct clock_info *ci = ph->get_priv(ph);
struct scmi_clock_info *clk = ci->clk + clk_id;
if (clk_id >= ci->num_clocks)
return NULL;
clk = ci->clk + clk_id;
if (!clk->name[0])
return NULL;
......
......@@ -106,6 +106,7 @@ enum scmi_optee_pta_cmd {
* @channel_id: OP-TEE channel ID used for this transport
* @tee_session: TEE session identifier
* @caps: OP-TEE SCMI channel capabilities
* @rx_len: Response size
* @mu: Mutex protection on channel access
* @cinfo: SCMI channel information
* @shmem: Virtual base address of the shared memory
......
......@@ -166,9 +166,13 @@ static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
struct scmi_xfer *t;
struct scmi_msg_reset_domain_reset *dom;
struct scmi_reset_info *pi = ph->get_priv(ph);
struct reset_dom_info *rdom = pi->dom_info + domain;
struct reset_dom_info *rdom;
if (rdom->async_reset)
if (domain >= pi->num_domains)
return -EINVAL;
rdom = pi->dom_info + domain;
if (rdom->async_reset && flags & AUTONOMOUS_RESET)
flags |= ASYNCHRONOUS_RESET;
ret = ph->xops->xfer_get_init(ph, RESET, sizeof(*dom), 0, &t);
......@@ -180,7 +184,7 @@ static int scmi_domain_reset(const struct scmi_protocol_handle *ph, u32 domain,
dom->flags = cpu_to_le32(flags);
dom->reset_state = cpu_to_le32(state);
if (rdom->async_reset)
if (flags & ASYNCHRONOUS_RESET)
ret = ph->xops->do_xfer_with_response(ph, t);
else
ret = ph->xops->do_xfer(ph, t);
......
......@@ -138,9 +138,28 @@ static int scmi_pm_domain_probe(struct scmi_device *sdev)
scmi_pd_data->domains = domains;
scmi_pd_data->num_domains = num_domains;
dev_set_drvdata(dev, scmi_pd_data);
return of_genpd_add_provider_onecell(np, scmi_pd_data);
}
static void scmi_pm_domain_remove(struct scmi_device *sdev)
{
int i;
struct genpd_onecell_data *scmi_pd_data;
struct device *dev = &sdev->dev;
struct device_node *np = dev->of_node;
of_genpd_del_provider(np);
scmi_pd_data = dev_get_drvdata(dev);
for (i = 0; i < scmi_pd_data->num_domains; i++) {
if (!scmi_pd_data->domains[i])
continue;
pm_genpd_remove(scmi_pd_data->domains[i]);
}
}
static const struct scmi_device_id scmi_id_table[] = {
{ SCMI_PROTOCOL_POWER, "genpd" },
{ },
......@@ -150,6 +169,7 @@ MODULE_DEVICE_TABLE(scmi, scmi_id_table);
static struct scmi_driver scmi_power_domain_driver = {
.name = "scmi-power-domain",
.probe = scmi_pm_domain_probe,
.remove = scmi_pm_domain_remove,
.id_table = scmi_id_table,
};
module_scmi_driver(scmi_power_domain_driver);
......
......@@ -762,6 +762,10 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
{
int ret;
struct scmi_xfer *t;
struct sensors_info *si = ph->get_priv(ph);
if (sensor_id >= si->num_sensors)
return -EINVAL;
ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_GET,
sizeof(__le32), sizeof(__le32), &t);
......@@ -771,7 +775,6 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,
put_unaligned_le32(sensor_id, t->tx.buf);
ret = ph->xops->do_xfer(ph, t);
if (!ret) {
struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;
*sensor_config = get_unaligned_le64(t->rx.buf);
......@@ -788,6 +791,10 @@ static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_config_set *msg;
struct sensors_info *si = ph->get_priv(ph);
if (sensor_id >= si->num_sensors)
return -EINVAL;
ret = ph->xops->xfer_get_init(ph, SENSOR_CONFIG_SET,
sizeof(*msg), 0, &t);
......@@ -800,7 +807,6 @@ static int scmi_sensor_config_set(const struct scmi_protocol_handle *ph,
ret = ph->xops->do_xfer(ph, t);
if (!ret) {
struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;
s->sensor_config = sensor_config;
......@@ -831,8 +837,11 @@ static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
struct scmi_sensor_info *s;
struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;
if (sensor_id >= si->num_sensors)
return -EINVAL;
ret = ph->xops->xfer_get_init(ph, SENSOR_READING_GET,
sizeof(*sensor), 0, &t);
......@@ -841,6 +850,7 @@ static int scmi_sensor_reading_get(const struct scmi_protocol_handle *ph,
sensor = t->tx.buf;
sensor->id = cpu_to_le32(sensor_id);
s = si->sensors + sensor_id;
if (s->async) {
sensor->flags = cpu_to_le32(SENSOR_READ_ASYNC);
ret = ph->xops->do_xfer_with_response(ph, t);
......@@ -895,9 +905,13 @@ scmi_sensor_reading_get_timestamped(const struct scmi_protocol_handle *ph,
int ret;
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
struct scmi_sensor_info *s;
struct sensors_info *si = ph->get_priv(ph);
struct scmi_sensor_info *s = si->sensors + sensor_id;
if (sensor_id >= si->num_sensors)
return -EINVAL;
s = si->sensors + sensor_id;
if (!count || !readings ||
(!s->num_axis && count > 1) || (s->num_axis && count > s->num_axis))
return -EINVAL;
......@@ -948,6 +962,9 @@ scmi_sensor_info_get(const struct scmi_protocol_handle *ph, u32 sensor_id)
{
struct sensors_info *si = ph->get_priv(ph);
if (sensor_id >= si->num_sensors)
return NULL;
return si->sensors + sensor_id;
}
......
......@@ -84,7 +84,7 @@ struct scmi_protocol_handle;
struct scmi_clk_proto_ops {
int (*count_get)(const struct scmi_protocol_handle *ph);
const struct scmi_clock_info *(*info_get)
const struct scmi_clock_info __must_check *(*info_get)
(const struct scmi_protocol_handle *ph, u32 clk_id);
int (*rate_get)(const struct scmi_protocol_handle *ph, u32 clk_id,
u64 *rate);
......@@ -466,7 +466,7 @@ enum scmi_sensor_class {
*/
struct scmi_sensor_proto_ops {
int (*count_get)(const struct scmi_protocol_handle *ph);
const struct scmi_sensor_info *(*info_get)
const struct scmi_sensor_info __must_check *(*info_get)
(const struct scmi_protocol_handle *ph, u32 sensor_id);
int (*trip_point_config)(const struct scmi_protocol_handle *ph,
u32 sensor_id, u8 trip_id, u64 trip_value);
......
......@@ -27,9 +27,9 @@ TRACE_EVENT(scmi_fc_call,
__entry->val2 = val2;
),
TP_printk("[0x%02X]:[0x%02X]:[%08X]:%u:%u",
__entry->protocol_id, __entry->msg_id,
__entry->res_id, __entry->val1, __entry->val2)
TP_printk("pt=%02X msg_id=%02X res_id:%u vals=%u:%u",
__entry->protocol_id, __entry->msg_id,
__entry->res_id, __entry->val1, __entry->val2)
);
TRACE_EVENT(scmi_xfer_begin,
......@@ -53,9 +53,9 @@ TRACE_EVENT(scmi_xfer_begin,
__entry->poll = poll;
),
TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u poll=%u",
__entry->transfer_id, __entry->msg_id, __entry->protocol_id,
__entry->seq, __entry->poll)
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X poll=%u",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->poll)
);
TRACE_EVENT(scmi_xfer_response_wait,
......@@ -81,9 +81,9 @@ TRACE_EVENT(scmi_xfer_response_wait,
__entry->poll = poll;
),
TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u tmo_ms=%u poll=%u",
__entry->transfer_id, __entry->msg_id, __entry->protocol_id,
__entry->seq, __entry->timeout, __entry->poll)
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X tmo_ms=%u poll=%u",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->timeout, __entry->poll)
);
TRACE_EVENT(scmi_xfer_end,
......@@ -107,9 +107,9 @@ TRACE_EVENT(scmi_xfer_end,
__entry->status = status;
),
TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u status=%d",
__entry->transfer_id, __entry->msg_id, __entry->protocol_id,
__entry->seq, __entry->status)
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X s=%d",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->status)
);
TRACE_EVENT(scmi_rx_done,
......@@ -133,9 +133,9 @@ TRACE_EVENT(scmi_rx_done,
__entry->msg_type = msg_type;
),
TP_printk("transfer_id=%d msg_id=%u protocol_id=%u seq=%u msg_type=%u",
__entry->transfer_id, __entry->msg_id, __entry->protocol_id,
__entry->seq, __entry->msg_type)
TP_printk("pt=%02X msg_id=%02X seq=%04X transfer_id=%X msg_type=%u",
__entry->protocol_id, __entry->msg_id, __entry->seq,
__entry->transfer_id, __entry->msg_type)
);
TRACE_EVENT(scmi_msg_dump,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment