From patchwork Thu Nov 30 14:58:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Konrad Dybcio X-Patchwork-Id: 171947 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:bcd1:0:b0:403:3b70:6f57 with SMTP id r17csp445394vqy; Thu, 30 Nov 2023 06:58:47 -0800 (PST) X-Google-Smtp-Source: AGHT+IHlgT81dPaGHWHKD6yOe8rJkwpWm6bZ+GergKUrTG8X0Pjw871OSRgv614gHTOc5tw29UXV X-Received: by 2002:a05:6a00:3a17:b0:6bd:2c0a:e82 with SMTP id fj23-20020a056a003a1700b006bd2c0a0e82mr25575653pfb.7.1701356326359; Thu, 30 Nov 2023 06:58:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701356326; cv=none; d=google.com; s=arc-20160816; b=w143+Vc/JWhyuF1lOzp6OquC+QsFw28j0+pBfV35355f6/IHB0G1zm78GJLwAsPPK7 ahUPfH81ydwfb0c6r73d4pAOCyVxdZFashtLPmZI316KSUCjW81F7sZyFXgxlOifBSJx DffN0lFYnA1JXhxp6zDH7uS4nULeZjcJUhDefH6371305AeCrsP1vOPcAnAOe81cb9fG AnBq3Je7auIIendFys1JBHlCNmMhM+QA0Gcfvl5Q5KELRb+MMv3M/zC+A9YIEPcTAF8A VAqptU6geL7K//veLuFACmrpglQgdptiRyAB/yQhhgxXBBPkVFYHhfwyWppoU/BGLtAb 9sIA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=FEWaT4vWmB9FPKlxuE8ZsMpGec2h+D+gnsnqlOC+FWw=; fh=hXnaC5mvBa1lAyt+9YMdqgJPlSfEfXcUZbLK0Lo9wS8=; b=JTHzrzf9tTWbwtOYpoLXC0+sUVmHaFVVdx1Kk1Zq7BmqwxBW2cLhbKkNTaL0bqzcP/ RcFXkJKDjoFeK4/gVUNRHVxDBVxY24D97SpVn06YBHpQ3sMimxLd2OJK2G138z86pfKI K9PaH/67klAPk+be+IFalyN/FFg7ILWm93E5ep9X0ymbdL/hACr95FXgPph6nnf5ad4N kHNBStRr0CERBbBIX3L3l4fjuz1lWVwY0++hUWEdVb9nTDUj2ZI4nXvQsGlmzqiwp+I6 Ys7l9BtVAmVU50T0a/E7g+keaGvT83oG8le1JU9IgP1im/CZsWXkYJEy9A8VWEFgHPam C9TQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=vnhsGY89; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from agentk.vger.email (agentk.vger.email. [23.128.96.32]) by mx.google.com with ESMTPS id y18-20020a056a00191200b006cd904d87ddsi1441724pfi.44.2023.11.30.06.58.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 06:58:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) client-ip=23.128.96.32; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=vnhsGY89; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.32 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by agentk.vger.email (Postfix) with ESMTP id 5BFE88093C82; Thu, 30 Nov 2023 06:58:40 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346185AbjK3O61 (ORCPT + 99 others); Thu, 30 Nov 2023 09:58:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49230 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346156AbjK3O6X (ORCPT ); Thu, 30 Nov 2023 09:58:23 -0500 Received: from mail-ed1-x52b.google.com (mail-ed1-x52b.google.com [IPv6:2a00:1450:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0DB110D5 for ; Thu, 30 Nov 2023 06:58:28 -0800 (PST) Received: by mail-ed1-x52b.google.com with SMTP id 4fb4d7f45d1cf-54b450bd014so1116557a12.3 for ; Thu, 30 Nov 2023 06:58:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1701356307; x=1701961107; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=FEWaT4vWmB9FPKlxuE8ZsMpGec2h+D+gnsnqlOC+FWw=; b=vnhsGY89wdTqXzmws+jns2gkOizWSLwPUVYkbMAsNJs3C8Xjigja3UyjoOU430UeAS tfG4iSSkTrsAIKiS7yrqa5o5p6bgQQ6tOHWUBOKzSir3YL2V+QeBdeFiI/rpng8n7mlR TfMidStH8w8ptL5dpW11vExK3mVFj2t43hVsB24jt5FXD/mhDv6J8xo9fVeq10+/DPE0 SmnkSGi9Ag2j7/srLdursJvf3nZO3cBl7LVZZsmtcpUeYgmQB12xywm3jXzD2Wvgj7D2 9A4jYHUuWEbi+yGJ/5AzbSJBCUtnBGwVcKR4Trnr0XQ1UY7l1qCxaHPXcqUps7GQEtSz Dt6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701356307; x=1701961107; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FEWaT4vWmB9FPKlxuE8ZsMpGec2h+D+gnsnqlOC+FWw=; b=lzSazBdTMVk51AkJ3UjMdBP9mREQZ+UZIlRrGc/685iy9u/S1w2CCIEqG3AZwlyCN6 Au8GZYgTxDyA+IKuQ2/QV/BSQtxBqTfpMnzoZn5RjZ4qiQeLQ5QlK7V2WU1LqpnpE3vW 0o21U/AnUYte15OtsoCCB2MjreIothdoy3TJxWoYvihZvh/MU4fYiWCeTUK/iycE/JJB a06bfFZy4lFOJ0bd9/NhVr42snJAX9VRx8LsDttvhNWsEMiSGu0SV+dIhLHuNVacrimg +XC6hSAupkiULPjEqteU+4EpBvh2nJ0Y0zLgr3kz5NbD4qdZX5nNICn8zWXSalUPfxfZ Kz6g== X-Gm-Message-State: AOJu0Yykokd2IPJVYw/F4VtHStUElreQ7zsEkU3mpxmoxNs4oa6Q3bPB uq5irv+tibQchhLT/EJoaZAxhg== X-Received: by 2002:a17:906:5307:b0:a09:589f:8853 with SMTP id h7-20020a170906530700b00a09589f8853mr14757421ejo.66.1701356307328; Thu, 30 Nov 2023 06:58:27 -0800 (PST) Received: from [10.167.154.1] (178235187166.dynamic-4-waw-k-2-3-0.vectranet.pl. [178.235.187.166]) by smtp.gmail.com with ESMTPSA id a5-20020a17090640c500b009e50ea0a05asm756753ejk.99.2023.11.30.06.58.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Nov 2023 06:58:27 -0800 (PST) From: Konrad Dybcio Date: Thu, 30 Nov 2023 15:58:22 +0100 Subject: [PATCH 2/3] soc: qcom: stats: Add DDR sleep stats MIME-Version: 1.0 Message-Id: <20231130-topic-ddr_sleep_stats-v1-2-5981c2e764b6@linaro.org> References: <20231130-topic-ddr_sleep_stats-v1-0-5981c2e764b6@linaro.org> In-Reply-To: <20231130-topic-ddr_sleep_stats-v1-0-5981c2e764b6@linaro.org> To: Andy Gross , Bjorn Andersson , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Maulik Shah Cc: Marijn Suijten , linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Konrad Dybcio X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1701356302; l=7789; i=konrad.dybcio@linaro.org; s=20230215; h=from:subject:message-id; bh=n247b3gscc6TQzkRebaWpfpSPhntN+5rBPC03jA9Nlw=; b=pquLU0BKQ6uVxtgV2+o/+kiSu+6/SuinRalqCnajEMKMU120Sw1UvjY/mYzKPOWcvLN74U395 3PzqcQeldxHDYc6iIR8UYsQyRBwAvJZjnKoN20NCDQJh4KIgfrigEzh X-Developer-Key: i=konrad.dybcio@linaro.org; a=ed25519; pk=iclgkYvtl2w05SSXO5EjjSYlhFKsJ+5OSZBjOkQuEms= X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (agentk.vger.email [0.0.0.0]); Thu, 30 Nov 2023 06:58:40 -0800 (PST) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1784001411206428755 X-GMAIL-MSGID: 1784001411206428755 Add DDR sleep stats that include: - the available RAM low power states - per-state residency information - per-frequency residency information (for some freqs only, it seems) - DDR vote information (AB/IB) and some magic thing that we're yet to decode. Based on the msm-5.4 downstream implementation, debugged with some help from Qualcomm's Maulik Shah. Signed-off-by: Konrad Dybcio --- drivers/soc/qcom/qcom_stats.c | 186 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 185 insertions(+), 1 deletion(-) diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 0216fc24f2ca..94ee543d2e8e 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -22,8 +23,20 @@ #define LAST_ENTERED_AT_OFFSET 0x8 #define LAST_EXITED_AT_OFFSET 0x10 #define ACCUMULATED_OFFSET 0x18 +#define DDR_DYNAMIC_OFFSET 0x1c + #define DDR_OFFSET_MASK GENMASK(9, 0) #define CLIENT_VOTES_OFFSET 0x20 +#define ARCH_TIMER_FREQ 19200000 +#define DDR_MAGIC_KEY1 0xA1157A75 /* leetspeak "ALLSTATS" */ +#define DDR_MAX_NUM_ENTRIES 20 + +#define DDR_VOTE_DRV_MAX 18 +#define DDR_VOTE_DRV_ABSENT 0xdeaddead +#define DDR_VOTE_DRV_INVALID 0xffffdead +#define DDR_VOTE_X GENMASK(27, 14) +#define DDR_VOTE_Y GENMASK(13, 0) + struct subsystem_data { const char *name; u32 smem_item; @@ -48,6 +61,7 @@ struct stats_config { bool appended_stats_avail; bool dynamic_offset; bool subsystem_stats_in_smem; + bool ddr_stats; }; struct stats_data { @@ -68,6 +82,25 @@ struct appended_stats { u32 reserved[3]; }; +struct ddr_stats_entry { + u32 name; + u32 count; + u64 dur; +} __packed; + +struct ddr_stats { + u32 key; + u32 entry_count; +#define MAX_DDR_STAT_ENTRIES 20 + struct ddr_stats_entry entry[MAX_DDR_STAT_ENTRIES]; +} __packed; + +struct ddr_stats_data { + struct device *dev; + void __iomem *base; + struct qmp *qmp; +}; + static void qcom_print_stats(struct seq_file *s, const struct sleep_stats *stat) { u64 accumulated = stat->accumulated; @@ -118,6 +151,108 @@ static int qcom_soc_sleep_stats_show(struct seq_file *s, void *unused) return 0; } +#define DDR_NAME_TYPE GENMASK(15, 8) + #define DDR_NAME_TYPE_LPM 0 + #define DDR_NAME_TYPE_FREQ 1 + +#define DDR_NAME_LPM_NAME GENMASK(7, 0) + +#define DDR_NAME_FREQ_MHZ GENMASK(31, 16) +#define DDR_NAME_FREQ_CP_IDX GENMASK(4, 0) +static void qcom_ddr_stats_print(struct seq_file *s, struct ddr_stats_entry *entry) +{ + u32 cp_idx, name; + u8 type; + + type = FIELD_GET(DDR_NAME_TYPE, entry->name); + + switch (type) { + case DDR_NAME_TYPE_LPM: + name = FIELD_GET(DDR_NAME_LPM_NAME, entry->name); + + seq_printf(s, "LPM | Type 0x%2x\tcount: %u\ttime: %llums\n", + name, entry->count, entry->dur); + break; + case DDR_NAME_TYPE_FREQ: + cp_idx = FIELD_GET(DDR_NAME_FREQ_CP_IDX, entry->name); + name = FIELD_GET(DDR_NAME_FREQ_MHZ, entry->name); + + /* Neither 0Mhz nor 0 votes is very interesting */ + if (!name || !entry->count) + return; + + seq_printf(s, "Freq | %dMHz (idx %u)\tcount: %u\ttime: %llums\n", + name, cp_idx, entry->count, entry->dur); + break; + default: + seq_printf(s, "Unknown data chunk (type = 0x%x count = 0x%x dur = 0x%llx)\n", + type, entry->count, entry->dur); + } +} + +static int qcom_ddr_stats_show(struct seq_file *s, void *unused) +{ + struct ddr_stats_data *ddrd = s->private; + struct ddr_stats ddr; + struct ddr_stats_entry *entry = ddr.entry; + u32 entry_count, stats_size; + u32 votes[DDR_VOTE_DRV_MAX]; + int i, ret; + + /* Request a stats sync, it may take some time to update though.. */ + ret = qmp_send(ddrd->qmp, "{class: ddr, action: freqsync}"); + if (ret) { + dev_err(ddrd->dev, "failed to send QMP message\n"); + return ret; + } + + entry_count = readl(ddrd->base + offsetof(struct ddr_stats, entry_count)); + if (entry_count > DDR_MAX_NUM_ENTRIES) + return -EINVAL; + + /* We're not guaranteed to have DDR_MAX_NUM_ENTRIES */ + stats_size = sizeof(ddr); + stats_size -= DDR_MAX_NUM_ENTRIES * sizeof(*entry); + stats_size += entry_count * sizeof(*entry); + + /* Copy and process the stats */ + memcpy_fromio(&ddr, ddrd->base, stats_size); + + for (i = 0; i < ddr.entry_count; i++) { + /* Convert the period to ms */ + entry[i].dur = mult_frac(MSEC_PER_SEC, entry[i].dur, ARCH_TIMER_FREQ); + } + + for (i = 0; i < ddr.entry_count; i++) + qcom_ddr_stats_print(s, &entry[i]); + + /* Ask AOSS to dump DDR votes */ + ret = qmp_send(ddrd->qmp, "{class: ddr, res: drvs_ddr_votes}"); + if (ret) { + dev_err(ddrd->dev, "failed to send QMP message\n"); + return ret; + } + + /* Subsystem votes */ + memcpy_fromio(votes, ddrd->base + stats_size, sizeof(u32) * DDR_VOTE_DRV_MAX); + + for (i = 0; i < DDR_VOTE_DRV_MAX; i++) { + u32 ab, ib; + + if (votes[i] == DDR_VOTE_DRV_ABSENT || votes[i] == DDR_VOTE_DRV_INVALID) + ab = ib = votes[i]; + else { + ab = FIELD_GET(DDR_VOTE_X, votes[i]); + ib = FIELD_GET(DDR_VOTE_Y, votes[i]); + } + + seq_printf(s, "Vote | AB = %5u\tIB = %5u\n", ab, ib); + } + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(qcom_ddr_stats); DEFINE_SHOW_ATTRIBUTE(qcom_soc_sleep_stats); DEFINE_SHOW_ATTRIBUTE(qcom_subsystem_sleep_stats); @@ -180,13 +315,56 @@ static void qcom_create_subsystem_stat_files(struct dentry *root, &qcom_subsystem_sleep_stats_fops); } +static int qcom_create_ddr_stats_files(struct device *dev, + struct dentry *root, + void __iomem *reg, + const struct stats_config *config) +{ + struct ddr_stats_data *ddrd; + u32 key, stats_offset; + struct dentry *dent; + + /* Nothing to do */ + if (!config->ddr_stats) + return 0; + + ddrd = devm_kzalloc(dev, sizeof(*ddrd), GFP_KERNEL); + if (!ddrd) + return dev_err_probe(dev, -ENOMEM, "Couldn't allocate DDR stats data\n"); + + ddrd->dev = dev; + + /* Get the offset of DDR stats */ + stats_offset = readl(reg + DDR_DYNAMIC_OFFSET) & DDR_OFFSET_MASK; + ddrd->base = reg + stats_offset; + + /* Check if DDR stats are present */ + key = readl(ddrd->base); + if (key != DDR_MAGIC_KEY1) + return 0; + + dent = debugfs_create_file("ddr_sleep_stats", 0400, root, ddrd, &qcom_ddr_stats_fops); + if (IS_ERR(dent)) + return PTR_ERR(dent); + + /* QMP is only necessary for DDR votes */ + ddrd->qmp = qmp_get(dev); + if (IS_ERR(ddrd->qmp)) { + dev_err(dev, "Couldn't get QMP mailbox: %ld. DDR votes won't be available.\n", + PTR_ERR(ddrd->qmp)); + debugfs_remove(dent); + } + + return 0; +} + static int qcom_stats_probe(struct platform_device *pdev) { void __iomem *reg; struct dentry *root; const struct stats_config *config; struct stats_data *d; - int i; + int i, ret; config = device_get_match_data(&pdev->dev); if (!config) @@ -208,6 +386,11 @@ static int qcom_stats_probe(struct platform_device *pdev) qcom_create_subsystem_stat_files(root, config); qcom_create_soc_sleep_stat_files(root, reg, d, config); + ret = qcom_create_ddr_stats_files(&pdev->dev, root, reg, config); + if (ret) { + debugfs_remove_recursive(root); + return ret; + }; platform_set_drvdata(pdev, root); @@ -254,6 +437,7 @@ static const struct stats_config rpmh_data = { .appended_stats_avail = false, .dynamic_offset = false, .subsystem_stats_in_smem = true, + .ddr_stats = true, }; static const struct of_device_id qcom_stats_table[] = {