Received: by 2002:a6b:500f:0:0:0:0:0 with SMTP id e15csp3021357iob; Mon, 16 May 2022 11:13:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxTCbrEzN6t//GlStidw6FqUvFbTIApBnGUbwoyoQjCl6BpABuKxv8rnhmca3ZR90WulbvI X-Received: by 2002:a17:907:7ea7:b0:6f4:7a72:da92 with SMTP id qb39-20020a1709077ea700b006f47a72da92mr16081229ejc.348.1652724794796; Mon, 16 May 2022 11:13:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1652724794; cv=none; d=google.com; s=arc-20160816; b=l0hER37fu1AQUH1Vs+ehbch/j/1ITg/Q2EdWFGQTgqRObzNM7JzSZbBJhMXZWQ7GEl eXtFJEofxL6CLFuNOGdMCXiylNJdRqmsZNOhvj3YxyI7Ins/avEjVlCJ1gKcX+TlnHES NkBebmV/YYWFvExkPKcWZ0AMHPVdTJireaVbN3eA6BkT0fZhChzJa2labfhiXESyglVX JgJmpke2ek2miJzeHZ+kv5W05CIVCkt1JTdXZV+Qy2ZmDUplE1S8O9BbyIFumtpFVo8g ePZl/3tA+3ajln2pV7/yABlKugWnnYw8b9XBPWiaqao0ztEoChkmlNFT8szQEm94loou STnw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=vGws4P6h8HiXN2PU2W4hKbAElmHlrUjmbT+dChMfh9w=; b=ssEVNWskJtGU0QQ7hNX9LmaWOKUbvS+ssbffWv85WZSjphwXKiSiavu7pU/G2M3n3S jYIHUI20Ykhj1UHG8MKCp/grqHtycfvjMvOQ9yzMLJ1PTBtaW3+FnAwZcNiV9/SIzPM5 5HyPHZ9sLDoqkMZNnXPGHLq4S7MYua1UdqNKRvwaoQ6G67C4ubglliKTp9ePVGvwlUbn hn+QlEWGEJngs+xLep2Qy0mEPeHIv9CnPHSSw96GqQAaB1HJi/wKTzJ8mQ5oNCFmHLLB 4ijjQ2eKoWL3L6UAKAdiEvHAByCRqPYSFENLSviEBKClz1cXvd7WfaFRc5z4BGD1Xn+n 8c9w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=hisilicon.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id e16-20020a056402191000b00418c2b5bd52si13326734edz.52.2022.05.16.11.12.48; Mon, 16 May 2022 11:13:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=hisilicon.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243473AbiEPMxa (ORCPT + 99 others); Mon, 16 May 2022 08:53:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41724 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229963AbiEPMxS (ORCPT ); Mon, 16 May 2022 08:53:18 -0400 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B1DCD393E0; Mon, 16 May 2022 05:53:15 -0700 (PDT) Received: from canpemm500009.china.huawei.com (unknown [172.30.72.54]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4L1zfL3kXFzgYJ5; Mon, 16 May 2022 20:51:54 +0800 (CST) Received: from localhost.localdomain (10.67.164.66) by canpemm500009.china.huawei.com (7.192.105.203) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Mon, 16 May 2022 20:53:13 +0800 From: Yicong Yang To: , , , , , , , , CC: , , , , , , , , , , , , , , , , , , Subject: [PATCH v8 3/8] hwtracing: hisi_ptt: Add tune function support for HiSilicon PCIe Tune and Trace device Date: Mon, 16 May 2022 20:52:18 +0800 Message-ID: <20220516125223.32012-4-yangyicong@hisilicon.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20220516125223.32012-1-yangyicong@hisilicon.com> References: <20220516125223.32012-1-yangyicong@hisilicon.com> MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.67.164.66] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To canpemm500009.china.huawei.com (7.192.105.203) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add tune function for the HiSilicon Tune and Trace device. The interface of tune is exposed through sysfs attributes of PTT PMU device. Signed-off-by: Yicong Yang Reviewed-by: Jonathan Cameron --- drivers/hwtracing/ptt/hisi_ptt.c | 157 +++++++++++++++++++++++++++++++ drivers/hwtracing/ptt/hisi_ptt.h | 23 +++++ 2 files changed, 180 insertions(+) diff --git a/drivers/hwtracing/ptt/hisi_ptt.c b/drivers/hwtracing/ptt/hisi_ptt.c index ef25ce98f664..c3fdb9bfb1b4 100644 --- a/drivers/hwtracing/ptt/hisi_ptt.c +++ b/drivers/hwtracing/ptt/hisi_ptt.c @@ -25,6 +25,161 @@ /* Dynamic CPU hotplug state used by PTT */ static enum cpuhp_state hisi_ptt_pmu_online; +static bool hisi_ptt_wait_tuning_finish(struct hisi_ptt *hisi_ptt) +{ + u32 val; + + return !readl_poll_timeout(hisi_ptt->iobase + HISI_PTT_TUNING_INT_STAT, + val, !(val & HISI_PTT_TUNING_INT_STAT_MASK), + HISI_PTT_WAIT_POLL_INTERVAL_US, + HISI_PTT_WAIT_TUNE_TIMEOUT_US); +} + +static int hisi_ptt_tune_data_get(struct hisi_ptt *hisi_ptt, + u32 event, u16 *data) +{ + u32 reg; + + reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); + reg &= ~(HISI_PTT_TUNING_CTRL_CODE | HISI_PTT_TUNING_CTRL_SUB); + reg |= FIELD_PREP(HISI_PTT_TUNING_CTRL_CODE | HISI_PTT_TUNING_CTRL_SUB, + event); + writel(reg, hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); + + /* Write all 1 to indicates it's the read process */ + writel(~0U, hisi_ptt->iobase + HISI_PTT_TUNING_DATA); + + if (!hisi_ptt_wait_tuning_finish(hisi_ptt)) + return -ETIMEDOUT; + + reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_DATA); + reg &= HISI_PTT_TUNING_DATA_VAL_MASK; + *data = FIELD_GET(HISI_PTT_TUNING_DATA_VAL_MASK, reg); + + return 0; +} + +static int hisi_ptt_tune_data_set(struct hisi_ptt *hisi_ptt, + u32 event, u16 data) +{ + u32 reg; + + reg = readl(hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); + reg &= ~(HISI_PTT_TUNING_CTRL_CODE | HISI_PTT_TUNING_CTRL_SUB); + reg |= FIELD_PREP(HISI_PTT_TUNING_CTRL_CODE | HISI_PTT_TUNING_CTRL_SUB, + event); + writel(reg, hisi_ptt->iobase + HISI_PTT_TUNING_CTRL); + + writel(FIELD_PREP(HISI_PTT_TUNING_DATA_VAL_MASK, data), + hisi_ptt->iobase + HISI_PTT_TUNING_DATA); + + if (!hisi_ptt_wait_tuning_finish(hisi_ptt)) + return -ETIMEDOUT; + + return 0; +} + +static ssize_t hisi_ptt_tune_attr_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct hisi_ptt *hisi_ptt = to_hisi_ptt(dev_get_drvdata(dev)); + struct dev_ext_attribute *ext_attr; + struct hisi_ptt_tune_desc *desc; + int ret; + u16 val; + + ext_attr = container_of(attr, struct dev_ext_attribute, attr); + desc = ext_attr->var; + + mutex_lock(&hisi_ptt->tune_lock); + ret = hisi_ptt_tune_data_get(hisi_ptt, desc->event_code, &val); + mutex_unlock(&hisi_ptt->tune_lock); + + if (ret) + return ret; + + return sysfs_emit(buf, "%u\n", val); +} + +static ssize_t hisi_ptt_tune_attr_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct hisi_ptt *hisi_ptt = to_hisi_ptt(dev_get_drvdata(dev)); + struct dev_ext_attribute *ext_attr; + struct hisi_ptt_tune_desc *desc; + int ret; + u16 val; + + ext_attr = container_of(attr, struct dev_ext_attribute, attr); + desc = ext_attr->var; + + if (kstrtou16(buf, 10, &val)) + return -EINVAL; + + mutex_lock(&hisi_ptt->tune_lock); + ret = hisi_ptt_tune_data_set(hisi_ptt, desc->event_code, val); + mutex_unlock(&hisi_ptt->tune_lock); + + if (ret) + return ret; + + return count; +} + +#define HISI_PTT_TUNE_ATTR(_name, _val, _show, _store) \ + static struct hisi_ptt_tune_desc _name##_desc = { \ + .name = #_name, \ + .event_code = _val, \ + }; \ + static struct dev_ext_attribute hisi_ptt_##_name##_attr = { \ + .attr = __ATTR(_name, 0600, _show, _store), \ + .var = &_name##_desc, \ + } + +#define HISI_PTT_TUNE_ATTR_COMMON(_name, _val) \ + HISI_PTT_TUNE_ATTR(_name, _val, \ + hisi_ptt_tune_attr_show, \ + hisi_ptt_tune_attr_store) + +/* + * The value of the tuning event are composed of two parts: main event code in bit[0,15] and + * subevent code in bit[16,23]. For example, qox_tx_cpl is a subevent of 'Tx path QoS control' + * which for tuning the weight of Tx completion TLPs. See hisi_ptt.rst documentation for + * more information. + */ +#define HISI_PTT_TUNE_QOS_TX_CPL (0x4 | (3 << 16)) +#define HISI_PTT_TUNE_QOS_TX_NP (0x4 | (4 << 16)) +#define HISI_PTT_TUNE_QOS_TX_P (0x4 | (5 << 16)) +#define HISI_PTT_TUNE_TX_PATH_IOB_RX_REQ_ALLOC_BUF_LEVEL (0x5 | (6 << 16)) +#define HISI_PTT_TUNE_TX_PATH_TX_REQ_ALLOC_BUF_LEVEL (0x5 | (7 << 16)) + +HISI_PTT_TUNE_ATTR_COMMON(qos_tx_cpl, + HISI_PTT_TUNE_QOS_TX_CPL); +HISI_PTT_TUNE_ATTR_COMMON(qos_tx_np, + HISI_PTT_TUNE_QOS_TX_NP); +HISI_PTT_TUNE_ATTR_COMMON(qos_tx_p, + HISI_PTT_TUNE_QOS_TX_P); +HISI_PTT_TUNE_ATTR_COMMON(tx_path_iob_rx_req_alloc_buf_level, + HISI_PTT_TUNE_TX_PATH_IOB_RX_REQ_ALLOC_BUF_LEVEL); +HISI_PTT_TUNE_ATTR_COMMON(tx_path_tx_req_alloc_buf_level, + HISI_PTT_TUNE_TX_PATH_TX_REQ_ALLOC_BUF_LEVEL); + +static struct attribute *hisi_ptt_tune_attrs[] = { + &hisi_ptt_qos_tx_cpl_attr.attr.attr, + &hisi_ptt_qos_tx_np_attr.attr.attr, + &hisi_ptt_qos_tx_p_attr.attr.attr, + &hisi_ptt_tx_path_iob_rx_req_alloc_buf_level_attr.attr.attr, + &hisi_ptt_tx_path_tx_req_alloc_buf_level_attr.attr.attr, + NULL, +}; + +static struct attribute_group hisi_ptt_tune_group = { + .attrs = hisi_ptt_tune_attrs, + .name = "tune", +}; + static u16 hisi_ptt_get_filter_val(u16 devid, bool is_port) { if (is_port) @@ -448,6 +603,7 @@ static const struct attribute_group *hisi_ptt_pmu_groups[] = { &hisi_ptt_cpumask_attr_group, &hisi_ptt_pmu_format_group, &hisi_ptt_pmu_filter_group, + &hisi_ptt_tune_group, NULL }; @@ -783,6 +939,7 @@ static int hisi_ptt_register_pmu(struct hisi_ptt *hisi_ptt) if (ret) return ret; + mutex_init(&hisi_ptt->tune_lock); spin_lock_init(&hisi_ptt->pmu_lock); hisi_ptt->hisi_ptt_pmu = (struct pmu) { diff --git a/drivers/hwtracing/ptt/hisi_ptt.h b/drivers/hwtracing/ptt/hisi_ptt.h index 2344e4195648..439583e5fbcf 100644 --- a/drivers/hwtracing/ptt/hisi_ptt.h +++ b/drivers/hwtracing/ptt/hisi_ptt.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,11 @@ /* * The definition of the device registers and register fields. */ +#define HISI_PTT_TUNING_CTRL 0x0000 +#define HISI_PTT_TUNING_CTRL_CODE GENMASK(15, 0) +#define HISI_PTT_TUNING_CTRL_SUB GENMASK(23, 16) +#define HISI_PTT_TUNING_DATA 0x0004 +#define HISI_PTT_TUNING_DATA_VAL_MASK GENMASK(15, 0) #define HISI_PTT_TRACE_ADDR_SIZE 0x0800 #define HISI_PTT_TRACE_ADDR_BASE_LO_0 0x0810 #define HISI_PTT_TRACE_ADDR_BASE_HI_0 0x0814 @@ -37,6 +43,8 @@ #define HISI_PTT_TRACE_INT_STAT 0x0890 #define HISI_PTT_TRACE_INT_STAT_MASK GENMASK(3, 0) #define HISI_PTT_TRACE_INT_MASK 0x0894 +#define HISI_PTT_TUNING_INT_STAT 0x0898 +#define HISI_PTT_TUNING_INT_STAT_MASK BIT(0) #define HISI_PTT_TRACE_WR_STS 0x08a0 #define HISI_PTT_TRACE_WR_STS_WRITE GENMASK(27, 0) #define HISI_PTT_TRACE_WR_STS_BUFFER GENMASK(29, 28) @@ -59,6 +67,7 @@ #define HISI_PTT_RESET_TIMEOUT_US 10UL #define HISI_PTT_RESET_POLL_INTERVAL_US 1UL /* Poll timeout and interval for waiting hardware work to finish */ +#define HISI_PTT_WAIT_TUNE_TIMEOUT_US 1000000UL #define HISI_PTT_WAIT_TRACE_TIMEOUT_US 100UL #define HISI_PTT_WAIT_POLL_INTERVAL_US 10UL @@ -71,6 +80,18 @@ #define HISI_PTT_PMU_TYPE_MASK GENMASK(31, 24) #define HISI_PTT_PMU_FORMAT_MASK GENMASK(35, 32) +/** + * struct hisi_ptt_tune_desc - Describe tune event for PTT tune + * @hisi_ptt: PTT device this tune event belongs to + * @name: name of this event + * @event_code: code of the event + */ +struct hisi_ptt_tune_desc { + struct hisi_ptt *hisi_ptt; + const char *name; + u32 event_code; +}; + /** * struct hisi_ptt_dma_buffer - Describe a single trace buffer of PTT trace. * The detail of the data format is described @@ -144,6 +165,7 @@ struct hisi_ptt_pmu_buf { * @hisi_ptt_pmu: the pum device of trace * @iobase: base IO address of the device * @pdev: pci_dev of this PTT device + * @tune_lock: lock to serialize the tune process * @pmu_lock: lock to serialize the perf process * @upper_bdf: the upper BDF range of the PCI devices managed by this PTT device * @lower_bdf: the lower BDF range of the PCI devices managed by this PTT device @@ -157,6 +179,7 @@ struct hisi_ptt { struct pmu hisi_ptt_pmu; void __iomem *iobase; struct pci_dev *pdev; + struct mutex tune_lock; spinlock_t pmu_lock; u32 upper_bdf; u32 lower_bdf; -- 2.24.0