lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 7 Aug 2019 09:23:41 +0000
From:   Peng Fan <peng.fan@....com>
To:     Sudeep Holla <sudeep.holla@....com>,
        "linux-arm-kernel@...ts.infradead.org" 
        <linux-arm-kernel@...ts.infradead.org>
CC:     "linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
        Bo Zhang <bozhang.zhang@...adcom.com>,
        Jim Quinlan <james.quinlan@...adcom.com>,
        Volodymyr Babchuk <volodymyr_babchuk@...m.com>,
        Gaku Inami <gaku.inami.xh@...esas.com>,
        "aidapala@....qualcomm.com" <aidapala@....qualcomm.com>,
        "pajay@....qualcomm.com" <pajay@....qualcomm.com>,
        Etienne Carriere <etienne.carriere@...aro.org>,
        Souvik Chakravarty <Souvik.Chakravarty@....com>,
        "wesleys@...inx.com" <wesleys@...inx.com>,
        Felix Burton <fburton@...inx.com>,
        Saeed Nowshadi <saeed.nowshadi@...inx.com>,
        Ionela Voinescu <Ionela.Voinescu@....com>,
        Chris Redpath <Chris.Redpath@....com>,
        Quentin Perret <Quentin.Perret@....com>
Subject: RE: [PATCH v2 1/5] firmware: arm_scmi: Add discovery of SCMI v2.0
 performance fastchannels

> Subject: [PATCH v2 1/5] firmware: arm_scmi: Add discovery of SCMI v2.0
> performance fastchannels
> 
> SCMI v2.0 adds support for "FastChannel", a lightweight unidirectional
> channel that is dedicated to a single SCMI message type for controlling a
> specific platform resource. They do not use a message header as they are
> specialized for a single message.
> 
> Only PERFORMANCE_LIMITS_{SET,GET} and
> PERFORMANCE_LEVEL_{SET,GET} commands are supported over
> fastchannels. As they are optional, they need to be discovered by
> PERFORMANCE_DESCRIBE_FASTCHANNEL command.
> Further {LIMIT,LEVEL}_SET commands can have optional doorbell support.
> 
> Add support for discovery of these fastchannels.
> 
> Cc: Ionela Voinescu <Ionela.Voinescu@....com>
> Cc: Chris Redpath <Chris.Redpath@....com>
> Cc: Quentin Perret <Quentin.Perret@....com>
> Signed-off-by: Sudeep Holla <sudeep.holla@....com>
> ---
>  drivers/firmware/arm_scmi/perf.c | 153
> ++++++++++++++++++++++++++++++-
>  1 file changed, 149 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/firmware/arm_scmi/perf.c
> b/drivers/firmware/arm_scmi/perf.c
> index 3c8ae7cc35de..6cce3e82e81e 100644
> --- a/drivers/firmware/arm_scmi/perf.c
> +++ b/drivers/firmware/arm_scmi/perf.c
> @@ -5,7 +5,9 @@
>   * Copyright (C) 2018 ARM Ltd.
>   */
> 
> +#include <linux/bits.h>
>  #include <linux/of.h>
> +#include <linux/io.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_opp.h>
>  #include <linux/sort.h>
> @@ -21,6 +23,7 @@ enum scmi_performance_protocol_cmd {
>  	PERF_LEVEL_GET = 0x8,
>  	PERF_NOTIFY_LIMITS = 0x9,
>  	PERF_NOTIFY_LEVEL = 0xa,
> +	PERF_DESCRIBE_FASTCHANNEL = 0xb,
>  };
> 
>  struct scmi_opp {
> @@ -44,6 +47,7 @@ struct scmi_msg_resp_perf_domain_attributes {
>  #define SUPPORTS_SET_PERF_LVL(x)	((x) & BIT(30))
>  #define SUPPORTS_PERF_LIMIT_NOTIFY(x)	((x) & BIT(29))
>  #define SUPPORTS_PERF_LEVEL_NOTIFY(x)	((x) & BIT(28))
> +#define SUPPORTS_PERF_FASTCHANNELS(x)	((x) & BIT(27))
>  	__le32 rate_limit_us;
>  	__le32 sustained_freq_khz;
>  	__le32 sustained_perf_level;
> @@ -87,17 +91,56 @@ struct scmi_msg_resp_perf_describe_levels {
>  	} opp[0];
>  };
> 
> +struct scmi_perf_get_fc_info {
> +	__le32 domain;
> +	__le32 message_id;
> +};
> +
> +struct scmi_msg_resp_perf_desc_fc {
> +	__le32 attr;
> +#define SUPPORTS_DOORBELL(x)		((x) & BIT(0))
> +#define DOORBELL_REG_WIDTH(x)		FIELD_GET(GENMASK(2, 1), (x))
> +	__le32 rate_limit;
> +	__le32 chan_addr_low;
> +	__le32 chan_addr_high;
> +	__le32 chan_size;
> +	__le32 db_addr_low;
> +	__le32 db_addr_high;
> +	__le32 db_set_lmask;
> +	__le32 db_set_hmask;
> +	__le32 db_preserve_lmask;
> +	__le32 db_preserve_hmask;
> +};
> +
> +struct scmi_fc_db_info {
> +	int width;
> +	u64 set;
> +	u64 mask;
> +	void __iomem *addr;
> +};
> +
> +struct scmi_fc_info {
> +	void __iomem *level_set_addr;
> +	void __iomem *limit_set_addr;
> +	void __iomem *level_get_addr;
> +	void __iomem *limit_get_addr;
> +	struct scmi_fc_db_info *level_set_db;
> +	struct scmi_fc_db_info *limit_set_db;
> +};
> +
>  struct perf_dom_info {
>  	bool set_limits;
>  	bool set_perf;
>  	bool perf_limit_notify;
>  	bool perf_level_notify;
> +	bool perf_fastchannels;
>  	u32 opp_count;
>  	u32 sustained_freq_khz;
>  	u32 sustained_perf_level;
>  	u32 mult_factor;
>  	char name[SCMI_MAX_STR_SIZE];
>  	struct scmi_opp opp[MAX_OPPS];
> +	struct scmi_fc_info *fc_info;
>  };
> 
>  struct scmi_perf_info {
> @@ -162,6 +205,7 @@ scmi_perf_domain_attributes_get(const struct
> scmi_handle *handle, u32 domain,
>  		dom_info->set_perf = SUPPORTS_SET_PERF_LVL(flags);
>  		dom_info->perf_limit_notify =
> SUPPORTS_PERF_LIMIT_NOTIFY(flags);
>  		dom_info->perf_level_notify =
> SUPPORTS_PERF_LEVEL_NOTIFY(flags);
> +		dom_info->perf_fastchannels =
> SUPPORTS_PERF_FASTCHANNELS(flags);
>  		dom_info->sustained_freq_khz =
>  					le32_to_cpu(attr->sustained_freq_khz);
>  		dom_info->sustained_perf_level =
> @@ -250,7 +294,7 @@ scmi_perf_describe_levels_get(const struct
> scmi_handle *handle, u32 domain,  }
> 
>  static int scmi_perf_limits_set(const struct scmi_handle *handle, u32
> domain,
> -				u32 max_perf, u32 min_perf)
> +				   u32 max_perf, u32 min_perf)
>  {
>  	int ret;
>  	struct scmi_xfer *t;
> @@ -273,7 +317,7 @@ static int scmi_perf_limits_set(const struct
> scmi_handle *handle, u32 domain,  }
> 
>  static int scmi_perf_limits_get(const struct scmi_handle *handle, u32
> domain,
> -				u32 *max_perf, u32 *min_perf)
> +				   u32 *max_perf, u32 *min_perf)
>  {
>  	int ret;
>  	struct scmi_xfer *t;
> @@ -299,7 +343,7 @@ static int scmi_perf_limits_get(const struct
> scmi_handle *handle, u32 domain,  }
> 
>  static int scmi_perf_level_set(const struct scmi_handle *handle, u32
> domain,
> -			       u32 level, bool poll)
> +				  u32 level, bool poll)
>  {
>  	int ret;
>  	struct scmi_xfer *t;
> @@ -322,7 +366,7 @@ static int scmi_perf_level_set(const struct
> scmi_handle *handle, u32 domain,  }
> 
>  static int scmi_perf_level_get(const struct scmi_handle *handle, u32
> domain,
> -			       u32 *level, bool poll)
> +				  u32 *level, bool poll)
>  {
>  	int ret;
>  	struct scmi_xfer *t;
> @@ -343,6 +387,104 @@ static int scmi_perf_level_get(const struct
> scmi_handle *handle, u32 domain,
>  	return ret;
>  }
> 
> +static bool scmi_perf_fc_size_is_valid(u32 msg, u32 size) {
> +	if ((msg == PERF_LEVEL_GET || msg == PERF_LEVEL_SET) && size == 4)
> +		return true;
> +	if ((msg == PERF_LIMITS_GET || msg == PERF_LIMITS_SET) && size == 8)
> +		return true;
> +	return false;
> +}
> +
> +static void
> +scmi_perf_domain_desc_fc(const struct scmi_handle *handle, u32 domain,
> +			 u32 message_id, void __iomem **p_addr,
> +			 struct scmi_fc_db_info **p_db)
> +{
> +	int ret;
> +	u32 flags;
> +	u64 phys_addr;
> +	u8 size;
> +	void __iomem *addr;
> +	struct scmi_xfer *t;
> +	struct scmi_fc_db_info *db;
> +	struct scmi_perf_get_fc_info *info;
> +	struct scmi_msg_resp_perf_desc_fc *resp;
> +
> +	if (!p_addr)
> +		return;
> +
> +	ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_FASTCHANNEL,
> +				 SCMI_PROTOCOL_PERF,
> +				 sizeof(*info), sizeof(*resp), &t);
> +	if (ret)
> +		return;
> +
> +	info = t->tx.buf;
> +	info->domain = cpu_to_le32(domain);
> +	info->message_id = cpu_to_le32(message_id);
> +
> +	ret = scmi_do_xfer(handle, t);
> +	if (ret)
> +		goto err_xfer;
> +
> +	resp = t->rx.buf;
> +	flags = le32_to_cpu(resp->attr);
> +	size = le32_to_cpu(resp->chan_size);
> +	if (!scmi_perf_fc_size_is_valid(message_id, size))
> +		goto err_xfer;
> +
> +	phys_addr = le32_to_cpu(resp->chan_addr_low);
> +	phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32;
> +	addr = devm_ioremap(handle->dev, phys_addr, size);
> +	if (!addr)
> +		goto err_xfer;
> +	*p_addr = addr;
> +
> +	if (p_db && SUPPORTS_DOORBELL(flags)) {
> +		db = devm_kzalloc(handle->dev, sizeof(*db), GFP_KERNEL);
> +		if (!db)
> +			goto err_xfer;
> +
> +		size = 1 << DOORBELL_REG_WIDTH(flags);
> +		phys_addr = le32_to_cpu(resp->db_addr_low);
> +		phys_addr |= (u64)le32_to_cpu(resp->db_addr_high) << 32;
> +		addr = devm_ioremap(handle->dev, phys_addr, size);
> +		if (!addr)
> +			goto err_xfer;
> +
> +		db->addr = addr;
> +		db->width = size;
> +		db->set = le32_to_cpu(resp->db_set_lmask);
> +		db->set |= (u64)le32_to_cpu(resp->db_set_hmask) << 32;
> +		db->mask = le32_to_cpu(resp->db_preserve_lmask);
> +		db->mask |= (u64)le32_to_cpu(resp->db_preserve_hmask) << 32;
> +		*p_db = db;
> +	}
> +err_xfer:
> +	scmi_xfer_put(handle, t);
> +}
> +
> +static void scmi_perf_domain_init_fc(const struct scmi_handle *handle,
> +				     u32 domain, struct scmi_fc_info **p_fc) {
> +	struct scmi_fc_info *fc;
> +
> +	fc = devm_kzalloc(handle->dev, sizeof(*fc), GFP_KERNEL);
> +	if (!fc)
> +		return;
> +
> +	scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_SET,
> +				 &fc->level_set_addr, &fc->level_set_db);
> +	scmi_perf_domain_desc_fc(handle, domain, PERF_LEVEL_GET,
> +				 &fc->level_get_addr, NULL);
> +	scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_SET,
> +				 &fc->limit_set_addr, &fc->limit_set_db);
> +	scmi_perf_domain_desc_fc(handle, domain, PERF_LIMITS_GET,
> +				 &fc->limit_get_addr, NULL);
> +	*p_fc = fc;
> +}
> +
>  /* Device specific ops */
>  static int scmi_dev_domain_id(struct device *dev)  { @@ -494,6 +636,9
> @@ static int scmi_perf_protocol_init(struct scmi_handle *handle)
> 
>  		scmi_perf_domain_attributes_get(handle, domain, dom);
>  		scmi_perf_describe_levels_get(handle, domain, dom);
> +
> +		if (dom->perf_fastchannels)
> +			scmi_perf_domain_init_fc(handle, domain, &dom->fc_info);
>  	}
> 
>  	handle->perf_ops = &perf_ops;

Reviewed-by: Peng Fan <peng.fan@....com>

> --
> 2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ