Unverified Commit d4f1920d authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

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.com


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 12f09234 40d30cf6
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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
+7 −3
Original line number Diff line number Diff line
@@ -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);
+20 −0
Original line number Diff line number Diff line
@@ -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);
+21 −4
Original line number Diff line number Diff line
@@ -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;
}

Loading