From patchwork Wed May 12 21:17:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Leach X-Patchwork-Id: 12254691 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 11C11C433ED for ; Wed, 12 May 2021 21:21:58 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7405C611C9 for ; Wed, 12 May 2021 21:21:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7405C611C9 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:MIME-Version:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:References:In-Reply-To:Message-Id:Date:Subject:Cc:To :From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=GnRL6yHYt1JI9z3ZHVCYJCiQ/aOTT3kP+wxvLDHrBp0=; b=HCijHViFZKB38vn/Pxd7gKbgnV WzS8NsAraVYHyEySKQj2VaslAcPLn7XvGxD6m2IMNzjyjkpM+Tr6YzZilC6lV9qmW9McICzfF4ZDD dnPEq5ctD/TLidDLvcnjSEeFxOUVDGh37llFb9+mJKMaPOjRy1ATY3D4FscX2DAIwoZ5vh3xrdLoA zhyJOmU8aI8YrFYIS5uqS89bSXiUo5xkjs18DY8gxpoduqdwNffCeBxTY6YQ4E0ayiS7HrkYhsvhE xXe7DsL8nXCCUcdK6Rt7KwTic6he5/L7WdG59NSDdtaPCxwI93sVp6KnlyyFaNV7HZHdShp0S2vls lz2ZMidA==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lgwGO-0040m6-HU; Wed, 12 May 2021 21:19:28 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lgwF7-0040Sm-SE for linux-arm-kernel@desiato.infradead.org; Wed, 12 May 2021 21:18:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=References:In-Reply-To:Message-Id: Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description; bh=/2B+m3JQzCXJiqd3Y+kjLvDba4XsvQeCp6DFTa+jT8U=; b=ZzFie38OcjmexqYXV9IKQpTcTK u7NIYL05HdGp5ZefswwBUV7KkcyhjTaEWWgydP4l8fd9BEMcCrodXYBvZ9uM425euV6aRSvquzPXe qEgJK1/+rDEXbTLdYyoHrafuFH9w5m+A1Y1ZufivCDd+gb0q2uUuDRLL1ABGz/xaGdFXV8bQtzUqu 00VCbSBnFL6aXj5+HykTEdrloKD9Ng01D1vRQ6NG6E5+qrLIs0m/a/KJxL/G1cdzPBtAi08UKEhAU F9mx2KiGJt2hKN+sqeMKLSAKhBKGz5nbwuhezTt9efcGbYiLohevrF0oWRcDQPUpXIs4fOHfuZ0Eq vUid7oBw==; Received: from mail-wr1-x432.google.com ([2a00:1450:4864:20::432]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lgwF4-00Apfj-0Q for linux-arm-kernel@lists.infradead.org; Wed, 12 May 2021 21:18:08 +0000 Received: by mail-wr1-x432.google.com with SMTP id e7so6487632wrc.11 for ; Wed, 12 May 2021 14:18:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=/2B+m3JQzCXJiqd3Y+kjLvDba4XsvQeCp6DFTa+jT8U=; b=eSPQ3o5vSyxaq56JQrGZATEnXBuXINo8bzMt7wyW+50/2VoA6PJoWDz7v3G7zjO99U 5X1BOAjN3O5gK0aRJ8TOtyKXYUplmgBiyrcTvbdFqymEACfH2uZBYiJEr92sZN1P5SVV hmpnPXUOT+Zwo/7+/hsfvMNJrSDZbmJrOU/eOfm1CuLf+C2tMMTZcvFiGrv53+e5C7NI 1mi6p/YCJpO064j2nOyygLkgTlUZDQBt96dCkLkg81RrvRk9mBPTdoqlz2EYZdFn7WnJ MRzrWoJs+8KCgEoXyPobkTQ/BvmEwPUw3bheHzj7kFOMrUnjzxZ7BE8uX0PVlQfav3u6 YH/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=/2B+m3JQzCXJiqd3Y+kjLvDba4XsvQeCp6DFTa+jT8U=; b=f1FAuB+g/voVmqsilAxTBcvgr3bKhSEm0ps+tNcVG70016thyzTBsTyVRZ+MzGKb6x qkFf+vzDp2QuzcMsp1QfXYhNnCLqsALWnGdzspOK7NGkyzV0ci15+ZaMb1Tq4lLjgrMo NIqWxu8n26+JjBa7Nvy2/zVE91btRQda4bwtZSfX7nfoRzTGaKbqC+PSzaGVpcA2dmGH pTK0HCsd7oNyUFAOq/JnRj0+QLh7tDtpjecl6SCb9VyJ80QA0EIej79wfcDYAw6s0cgT tOI4tlVaeQfAbBXGQzaLlKraaN/sEz1XOv9VTaW+oNcH19iMRzeDJ+m1Q3BtXEWMQ65m OTpA== X-Gm-Message-State: AOAM533Sl+0U/XEyBkfeXnJwO8xXdn6XGUNWclA0yFP8MmoYImUMmJ99 V4Qwh00g93BvjchmwepzCyXuCXJMv2HOSg== X-Google-Smtp-Source: ABdhPJyK77ludpVOVh/ta9lgaeCx06I36IjnBUrXl8Zw6o3lYqEEWQbFD+Gf/P4BLH5pmNkYodG/SQ== X-Received: by 2002:a5d:590b:: with SMTP id v11mr47364103wrd.55.1620854284481; Wed, 12 May 2021 14:18:04 -0700 (PDT) Received: from linaro.org ([2a00:23c5:6809:2201:3d54:dc15:c65b:180c]) by smtp.gmail.com with ESMTPSA id e10sm908745wrw.20.2021.05.12.14.18.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 12 May 2021 14:18:04 -0700 (PDT) From: Mike Leach 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 Subject: [RFC PATCH 5/8] coresight: syscfg: Add API to check and validate device resources. Date: Wed, 12 May 2021 22:17:49 +0100 Message-Id: <20210512211752.4103-6-mike.leach@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210512211752.4103-1-mike.leach@linaro.org> References: <20210512211752.4103-1-mike.leach@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210512_141806_106099_36BE3C00 X-CRM114-Status: GOOD ( 35.24 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.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 --- .../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; }