linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Mike Leach <mike.leach@linaro.org>
To: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org, mathieu.poirier@linaro.org,
	suzuki.poulose@arm.com, leo.yan@linaro.org,
	Mike Leach <mike.leach@linaro.org>
Subject: [RFC PATCH 5/8] coresight: syscfg: Add API to check and validate device resources.
Date: Wed, 12 May 2021 22:17:49 +0100	[thread overview]
Message-ID: <20210512211752.4103-6-mike.leach@linaro.org> (raw)
In-Reply-To: <20210512211752.4103-1-mike.leach@linaro.org>

Adds in API to allow features which define device resources, to check
resource availability on load, and allocate on enable.

1) Check on load ensures that the resources required by the feature do
not exceed the maximum avialable on the device.

2) Allocate on enable ensures that sufficient unused resources are
available to satifsfy the feature on enable. Allocate can also be
used to resolve any resource selection requirements - i.e. select
an available resource from a pool of resources.

Signed-off-by: Mike Leach <mike.leach@linaro.org>
---
 .../hwtracing/coresight/coresight-config.c    | 71 +++++++++++++++---
 .../hwtracing/coresight/coresight-config.h    | 36 +++++++++-
 .../hwtracing/coresight/coresight-syscfg.c    | 72 +++++++++++++++++--
 3 files changed, 163 insertions(+), 16 deletions(-)

diff --git a/drivers/hwtracing/coresight/coresight-config.c b/drivers/hwtracing/coresight/coresight-config.c
index 3c501e027bc0..fdfda1975188 100644
--- a/drivers/hwtracing/coresight/coresight-config.c
+++ b/drivers/hwtracing/coresight/coresight-config.c
@@ -23,6 +23,10 @@ static void cscfg_set_reg(struct cscfg_regval_csdev *reg_csdev)
 	u32 *p_val32 = (u32 *)reg_csdev->driver_regval;
 	u32 tmp32 = reg_csdev->reg_desc.val32;
 
+	/* resource mapped registers may have custom handling in the device */
+	if (!reg_csdev->driver_regval)
+		return;
+
 	if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT) {
 		*((u64 *)reg_csdev->driver_regval) = reg_csdev->reg_desc.val64;
 		return;
@@ -43,6 +47,8 @@ static void cscfg_save_reg(struct cscfg_regval_csdev *reg_csdev)
 {
 	if (!(reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_SAVE))
 		return;
+	if (!reg_csdev->driver_regval)
+		return;
 	if (reg_csdev->reg_desc.type & CS_CFG_REG_TYPE_VAL_64BIT)
 		reg_csdev->reg_desc.val64 = *(u64 *)(reg_csdev->driver_regval);
 	else
@@ -73,15 +79,20 @@ static void cscfg_init_reg_param(struct cscfg_feature_csdev *feat_csdev,
 /* set values into the driver locations referenced in cscfg_reg_csdev */
 static int cscfg_set_on_enable(struct cscfg_feature_csdev *feat_csdev)
 {
-	int i;
+	int i, err = 0;
 
 	spin_lock(feat_csdev->drv_spinlock);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_set_reg(&feat_csdev->regs_csdev[i]);
 	spin_unlock(feat_csdev->drv_spinlock);
+
+	if (feat_csdev->feat_ops->set_on_enable)
+		err = feat_csdev->feat_ops->set_on_enable(feat_csdev);
+
 	dev_dbg(&feat_csdev->csdev->dev, "Feature %s: %s",
-		feat_csdev->feat_desc->name, "set on enable");
-	return 0;
+		feat_csdev->feat_desc->name,
+		err ? "error on enable" : "set on enable");
+	return err;
 }
 
 /* copy back values from the driver locations referenced in cscfg_reg_csdev */
@@ -89,6 +100,9 @@ static void cscfg_save_on_disable(struct cscfg_feature_csdev *feat_csdev)
 {
 	int i;
 
+	if (feat_csdev->feat_ops->clear_on_disable)
+		feat_csdev->feat_ops->clear_on_disable(feat_csdev);
+
 	spin_lock(feat_csdev->drv_spinlock);
 	for (i = 0; i < feat_csdev->nr_regs; i++)
 		cscfg_save_reg(&feat_csdev->regs_csdev[i]);
@@ -217,6 +231,37 @@ static int cscfg_update_curr_params(struct cscfg_config_csdev *config_csdev)
 	return 0;
 }
 
+static void cscfg_clear_res_config(struct cscfg_config_csdev *config_csdev)
+{
+	int i;
+	struct cscfg_feature_csdev *feat_csdev;
+
+	for (i = 0; i < config_csdev->nr_feat; i++) {
+		feat_csdev = config_csdev->feats_csdev[i];
+		if (feat_csdev->feat_ops->clear_feat_res)
+			feat_csdev->feat_ops->clear_feat_res(feat_csdev);
+	}
+}
+
+#define FEAT_ALLOC_RES_FMT "coresight-syscfg: Insufficient resource to enable feature %s\n"
+static int cscfg_alloc_res_config(struct cscfg_config_csdev *config_csdev)
+{
+	int err = 0, i;
+	struct cscfg_feature_csdev *feat_csdev;
+
+	for (i = 0; i < config_csdev->nr_feat; i++) {
+		feat_csdev = config_csdev->feats_csdev[i];
+		if (feat_csdev->feat_ops->alloc_feat_res)
+			err = feat_csdev->feat_ops->alloc_feat_res(feat_csdev);
+		if (err) {
+			pr_warn(FEAT_ALLOC_RES_FMT, feat_csdev->feat_desc->name);
+			cscfg_clear_res_config(config_csdev);
+			break;
+		}
+	}
+	return err;
+}
+
 /*
  * Configuration values will be programmed into the driver locations if enabling, or read
  * from relevant locations on disable.
@@ -227,19 +272,29 @@ static int cscfg_prog_config(struct cscfg_config_csdev *config_csdev, bool enabl
 	struct cscfg_feature_csdev *feat_csdev;
 	struct coresight_device *csdev;
 
+	/* check we have resources to enable this */
+	if (enable) {
+		err = cscfg_alloc_res_config(config_csdev);
+		if (err)
+			return err;
+	} else
+		cscfg_clear_res_config(config_csdev);
+
 	for (i = 0; i < config_csdev->nr_feat; i++) {
 		feat_csdev = config_csdev->feats_csdev[i];
 		csdev = feat_csdev->csdev;
 		dev_dbg(&csdev->dev, "cfg %s;  %s feature:%s", config_csdev->config_desc->name,
 			enable ? "enable" : "disable", feat_csdev->feat_desc->name);
 
-		if (enable)
+		if (enable) {
 			err = cscfg_set_on_enable(feat_csdev);
-		else
+			if (err) {
+				/* failed to enable - release any resources */
+				cscfg_clear_res_config(config_csdev);
+				break;
+			}
+		} else
 			cscfg_save_on_disable(feat_csdev);
-
-		if (err)
-			break;
 	}
 	return err;
 }
diff --git a/drivers/hwtracing/coresight/coresight-config.h b/drivers/hwtracing/coresight/coresight-config.h
index 9bd44b940add..0e46832df993 100644
--- a/drivers/hwtracing/coresight/coresight-config.h
+++ b/drivers/hwtracing/coresight/coresight-config.h
@@ -199,6 +199,8 @@ struct cscfg_parameter_csdev {
  * @params_csdev:	current parameter values on this device
  * @nr_regs:		number of registers to be programmed.
  * @regs_csdev:		Programming details for the registers
+ * @res_used:		Device specific context for resources used on enable.
+ * @feat_ops:		Feature operations to support alloc/release of resources.
  */
 struct cscfg_feature_csdev {
 	const struct cscfg_feature_desc *feat_desc;
@@ -209,6 +211,8 @@ struct cscfg_feature_csdev {
 	struct cscfg_parameter_csdev *params_csdev;
 	int nr_regs;
 	struct cscfg_regval_csdev *regs_csdev;
+	void *res_used;
+	struct cscfg_csdev_feat_ops *feat_ops;
 };
 
 /**
@@ -238,14 +242,44 @@ struct cscfg_config_csdev {
  * Coresight device operations.
  *
  * Registered coresight devices provide these operations to manage feature
- * instances compatible with the device hardware and drivers
+ * instances compatible with the device hardware and drivers.
+ *
+ * The @check_feat_res function can be used at load time to see if the device has
+ * sufficient resources to support the feature. This takes into account all resources
+ * on the device. e.g. if the feature requires three counters, and the device has a
+ * total of two implemented counters, this will return a -ENODEV error.
+ *
+ * The @alloc_feat_res function checks if there are sufficient unallocated resources
+ * left to enable the feature. This allows for multiple features being loaded that
+ * may compete for resources and also selects and allocates resources at enable time.
+ * e.g. if a feature requires two comparators, and there is only one left unallocated,
+ * then this will return a -ENOSPC error.
  *
  * @load_feat:	Pass a feature descriptor into the device and create the
  *		loaded feature instance (struct cscfg_feature_csdev).
+ * @check_feat_res: Check that the coresight device has sufficient resources to
+ *		    load the feature. Optional function. Return -ENODEV if this device
+ *                  does not have enough resources. Called before @load_feat for feature
+ *		    to ensure all feature can be installed on device.
+ * @alloc_feat_res: Allocate release feature resources when enabling a feature on the device
+ *		  . Optional function. Returns -ENOSPC if the device has not enough available
+ *		    resources to enable the feature. Called before registers programmed.
+ * @clear_feat_res: Release allocated resources. Must be implemented if @alloc_feat_res is
+ *		    implemented.
+ * @set_on_enable : Optional programming specific to device. Called immediately after
+ *		    generic register programming operation.
+ * @clear_on_disable: Optional programming specific to device. Called before generic register
+ *		      save operation.
  */
 struct cscfg_csdev_feat_ops {
 	int (*load_feat)(struct coresight_device *csdev,
 			 struct cscfg_feature_csdev *feat_csdev);
+	int (*check_feat_res)(struct coresight_device *csdev,
+			      struct cscfg_feature_desc *feat_desc);
+	int (*alloc_feat_res)(struct cscfg_feature_csdev *feat_csdev);
+	void (*clear_feat_res)(struct cscfg_feature_csdev *feat_csdev);
+	int (*set_on_enable)(struct cscfg_feature_csdev *feat_csdev);
+	void (*clear_on_disable)(struct cscfg_feature_csdev *feat_csdev);
 };
 
 /* coresight config helper functions*/
diff --git a/drivers/hwtracing/coresight/coresight-syscfg.c b/drivers/hwtracing/coresight/coresight-syscfg.c
index ab74e33b892b..984459c8f168 100644
--- a/drivers/hwtracing/coresight/coresight-syscfg.c
+++ b/drivers/hwtracing/coresight/coresight-syscfg.c
@@ -121,7 +121,8 @@ static int cscfg_add_cfg_to_csdevs(struct cscfg_config_desc *config_desc)
  * memory allocated using the csdev->dev object using devm managed allocator.
  */
 static struct cscfg_feature_csdev *
-cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc)
+cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc *feat_desc,
+		       struct cscfg_csdev_feat_ops *ops)
 {
 	struct cscfg_feature_csdev *feat_csdev = NULL;
 	struct device *dev = csdev->dev.parent;
@@ -165,9 +166,16 @@ cscfg_alloc_csdev_feat(struct coresight_device *csdev, struct cscfg_feature_desc
 	if (!feat_csdev->regs_csdev)
 		return NULL;
 
+	/* copy the static register info */
+	for (i = 0; i < feat_desc->nr_regs; i++) {
+		memcpy(&feat_csdev->regs_csdev[i].reg_desc,
+		       &feat_desc->regs_desc[i], sizeof(struct cscfg_regval_desc));
+	}
+
 	/* load the feature default values */
 	feat_csdev->feat_desc = feat_desc;
 	feat_csdev->csdev = csdev;
+	feat_csdev->feat_ops = ops;
 
 	return feat_csdev;
 }
@@ -180,10 +188,7 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
 	struct cscfg_feature_csdev *feat_csdev;
 	int err;
 
-	if (!ops->load_feat)
-		return -EINVAL;
-
-	feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc);
+	feat_csdev = cscfg_alloc_csdev_feat(csdev, feat_desc, ops);
 	if (!feat_csdev)
 		return -ENOMEM;
 
@@ -201,6 +206,57 @@ static int cscfg_load_feat_csdev(struct coresight_device *csdev,
 	return 0;
 }
 
+#define WARN_RES_FMT "coresight-syscfg: Insufficient resources to load feature %s in device %s\n"
+#define PARAM_ERR_FMT "coresight-syscfg: Cannot load feature %s. Invalid parameter index\n"
+
+/*
+ * Check if device supports resource check function, and check for sufficient resources
+ * to load feature onto device. Validate parameter references.
+ *
+ * Load feature if sufficient resources & valid parameter references.
+ */
+static int cscfg_check_feat_res_load(struct coresight_device *csdev,
+				     struct cscfg_feature_desc *feat_desc,
+				     struct cscfg_csdev_feat_ops *ops)
+{
+	int err = 0, i;
+
+	/* if we cannot load - fail early */
+	if (!ops->load_feat)
+		return -EINVAL;
+
+	/* ensure matched resource ops */
+	if ((ops->alloc_feat_res && !ops->clear_feat_res) ||
+	    (!ops->alloc_feat_res && ops->clear_feat_res))
+		return -EINVAL;
+
+	/* ensure that the coresight device can support the feature */
+	if (ops->check_feat_res) {
+		err = ops->check_feat_res(csdev, feat_desc);
+		if (err == -ENODEV) {
+			/* treat as mismatch, warn and continue */
+			pr_warn(WARN_RES_FMT, feat_desc->name,
+				dev_name(&csdev->dev));
+			return 0;
+		}
+	}
+
+	/* check parameter indexes are valid */
+	for (i = 0; i < feat_desc->nr_regs; i++) {
+		if (feat_desc->regs_desc[i].type & CS_CFG_REG_TYPE_VAL_PARAM) {
+			if (feat_desc->regs_desc[i].param_idx >= feat_desc->nr_params) {
+				pr_err(PARAM_ERR_FMT, feat_desc->name);
+				return -EINVAL;
+			}
+		}
+	}
+
+	/* sufficient resources - load if no other error */
+	if (!err)
+		err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
+	return err;
+}
+
 /*
  * Add feature to any matching devices - call with mutex locked.
  * Iterates through devices - any device that matches the feature will be
@@ -213,7 +269,9 @@ static int cscfg_add_feat_to_csdevs(struct cscfg_feature_desc *feat_desc)
 
 	list_for_each_entry(csdev_item, &cscfg_mgr->csdev_desc_list, item) {
 		if (csdev_item->match_flags & feat_desc->match_flags) {
-			err = cscfg_load_feat_csdev(csdev_item->csdev, feat_desc, &csdev_item->ops);
+			/* check sufficient resources and load feature */
+			err = cscfg_check_feat_res_load(csdev_item->csdev, feat_desc,
+							&csdev_item->ops);
 			if (err)
 				return err;
 		}
@@ -616,7 +674,7 @@ static int cscfg_add_feats_csdev(struct coresight_device *csdev,
 
 	list_for_each_entry(feat_desc, &cscfg_mgr->feat_desc_list, item) {
 		if (feat_desc->match_flags & match_flags) {
-			err = cscfg_load_feat_csdev(csdev, feat_desc, ops);
+			err = cscfg_check_feat_res_load(csdev, feat_desc, ops);
 			if (err)
 				break;
 		}
-- 
2.17.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2021-05-12 21:21 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-12 21:17 [RFC PATCH 0/8] coresight: syscfg: dynamic load, resource management Mike Leach
2021-05-12 21:17 ` [RFC PATCH 1/8] coresight: syscfg: Update API to allow dynamic load and unload Mike Leach
2021-05-17 17:15   ` Mathieu Poirier
2021-05-17 17:27     ` Mathieu Poirier
2021-05-19 13:28       ` Mike Leach
2021-05-12 21:17 ` [RFC PATCH 2/8] coresight: syscfg: Update load API for config loadable modules Mike Leach
2021-05-17 17:38   ` Mathieu Poirier
2021-05-12 21:17 ` [RFC PATCH 3/8] coresight: syscfg: Example CoreSight configuration loadable module Mike Leach
2021-05-18 15:52   ` Mathieu Poirier
2021-05-18 16:38     ` Mike Leach
2021-05-18 21:15       ` Mathieu Poirier
2021-05-12 21:17 ` [RFC PATCH 4/8] coresight: configfs: Allow configfs to activate configuration Mike Leach
2021-05-18 19:36   ` Mathieu Poirier
2021-05-19  9:47     ` Mike Leach
2021-05-12 21:17 ` Mike Leach [this message]
2021-05-21 17:56   ` [RFC PATCH 5/8] coresight: syscfg: Add API to check and validate device resources Mathieu Poirier
2021-07-08 16:30     ` Mike Leach
2021-05-12 21:17 ` [RFC PATCH 6/8] coresight: etm4x: syscfg: Add resource management to etm4x Mike Leach
2021-05-26 17:51   ` Mathieu Poirier
2021-05-27 17:41   ` Mathieu Poirier
2021-05-28 16:17   ` Mathieu Poirier
2021-07-09  9:32     ` Mike Leach
2021-05-12 21:17 ` [RFC PATCH 7/8] coresight: etm4x: Update perf event resource handling Mike Leach
2021-05-12 21:17 ` [RFC PATCH 8/8] coresight: etm4x: Update configuration example Mike Leach
2021-05-13 15:56 ` [RFC PATCH 0/8] coresight: syscfg: dynamic load, resource management Mathieu Poirier
2021-05-13 16:53   ` Mike Leach
2021-05-14  1:35     ` Leo Yan
2021-05-18 18:31 ` Suzuki K Poulose
2021-05-19  9:43   ` Mike Leach
2021-05-19 15:37     ` Mathieu Poirier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210512211752.4103-6-mike.leach@linaro.org \
    --to=mike.leach@linaro.org \
    --cc=coresight@lists.linaro.org \
    --cc=leo.yan@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=mathieu.poirier@linaro.org \
    --cc=suzuki.poulose@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).