Unverified Commit 77abf472 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'scmi-updates-5.20' of...

Merge tag 'scmi-updates-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers

Arm SCMI updates for v5.20

The main additions this time around are:

1. The capability to trace full SCMI message headers and payloads.
   The recent unearthing of chain of old firmware issues motivated
   this effort so that it is easier to trace them and debug quicker
   than it took this time around in absence of such tracing.

2. SCMI System power control driver to handle platform's requests for a
   graceful shutdown. Though the system power control protocol has been
   around since the begining of SCMI, it lacked the timeout information
   that was added in SCMI v3.1 that enables kernel to take appropriate
   action within the timeout and doesn't have to rely on any other
   user inputs(which was blocking factor for addition of this driver
   earlier)

3. Support for SCMI Power Capping protocol that was introduced in SCMI v3.1
   This protocol is intended for controlling and monitoring the power
   consumption of power capping domains. The firmware also provides the
   hierarchy of powercap domains by providing parent domain information.

It also contains a bug fix in the old SCPI driver addressing possible
user-after-free issues.

* tag 'scmi-updates-5.20' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scmi: Use fast channel tracing
  include: trace: Add SCMI fast channel tracing
  firmware: arm_scmi: Add SCMI v3.1 powercap fast channels support
  firmware: arm_scmi: Generalize the fast channel support
  firmware: arm_scmi: Add SCMI v3.1 powercap protocol basic support
  dt-bindings: firmware: arm,scmi: Add support for powercap protocol
  firmware: arm_scmi: Add SCMI System Power Control driver
  firmware: arm_scmi: Add devm_protocol_acquire helper
  firmware: arm_scmi: Add SCMI v3.1 System Power extensions
  firmware: arm_scmi: Support only one single system power device
  firmware: arm_scmi: Use new SCMI full message tracing
  include: trace: Add SCMI full message tracing
  firmware: arm_scpi: Ensure scpi_info is not assigned if the probe fails
  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/20220706115045.2272678-1-sudeep.holla@arm.com


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 3ed9222c b27d04d5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -183,6 +183,12 @@ properties:
            required:
              - reg

  protocol@18:
    type: object
    properties:
      reg:
        const: 0x18

additionalProperties: false

patternProperties:
@@ -323,6 +329,10 @@ examples:
                    };
                };
            };

            scmi_powercap: protocol@18 {
                reg = <0x18>;
            };
        };
    };

+12 −0
Original line number Diff line number Diff line
@@ -149,4 +149,16 @@ config ARM_SCMI_POWER_DOMAIN
	  will be called scmi_pm_domain. Note this may needed early in boot
	  before rootfs may be available.

config ARM_SCMI_POWER_CONTROL
	tristate "SCMI system power control driver"
	depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
	help
	  This enables System Power control logic which binds system shutdown or
	  reboot actions to SCMI System Power notifications generated by SCP
	  firmware.

	  This driver can also be built as a module.  If so, the module will be
	  called scmi_power_control. Note this may needed early in boot to catch
	  early shutdown/reboot SCMI requests.

endmenu
+2 −1
Original line number Diff line number Diff line
@@ -7,11 +7,12 @@ scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_SMC) += smc.o
scmi-transport-$(CONFIG_ARM_SCMI_HAVE_MSG) += msg.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_VIRTIO) += virtio.o
scmi-transport-$(CONFIG_ARM_SCMI_TRANSPORT_OPTEE) += optee.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o
scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o system.o voltage.o powercap.o
scmi-module-objs := $(scmi-bus-y) $(scmi-driver-y) $(scmi-protocols-y) \
		    $(scmi-transport-y)
obj-$(CONFIG_ARM_SCMI_PROTOCOL) += scmi-module.o
obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
obj-$(CONFIG_ARM_SCMI_POWER_CONTROL) += scmi_power_control.o

ifeq ($(CONFIG_THUMB2_KERNEL)$(CONFIG_CC_IS_CLANG),yy)
# The use of R7 in the SMCCC conflicts with the compiler's use of R7 as a frame
+3 −3
Original line number Diff line number Diff line
@@ -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);
}

+25 −1
Original line number Diff line number Diff line
@@ -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,
Loading