Received: by 2002:a05:6a10:5bc5:0:0:0:0 with SMTP id os5csp2649421pxb; Sun, 17 Oct 2021 21:36:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxUiAxIbbdKg3oPD4finRqzNrTMkC6gi/iyGhJe3i5gW3PkCejqoEC/4jlY+Gxuad86Q1yh X-Received: by 2002:a17:906:3542:: with SMTP id s2mr26807063eja.379.1634531790471; Sun, 17 Oct 2021 21:36:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1634531790; cv=none; d=google.com; s=arc-20160816; b=GGqJT5epDtuZMkkaPlQK0OCT/uJGkC+fIrgzqWdE4VcIfkJ3gUgcnaMRjBeikzZJ18 HDJ+0rLqLpEOyqI+MVjoMypQkZsdzQ2PCI8IWLfCOCmAIkvsbnuqcktC4W9EV4QCxUMz a5gen87KkP0jTUjMSon6XY48NlAmDM+UGjvUpYkAZ5AZ7VIsUytIIYMWTtTNIFEqhyng W/ggzPgAj+uEPspbUIxSG57lf/RlCKH3yvgFipIQr33CGCZJitr1W8eDv4lvq0egD1CM R4Xl3p1/CfA67isOXV9hD+/ryZg0URKJl+QpNZfngC9TumeXrLXnLOtTWEsYvzzaqhaf TXdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=fvwR23mhzoQ7xeungNzFzAcwJdDvCK9RNiPfd9p2NFQ=; b=uKsn1f8978yYKzHINJQNOKPag9H3Iuu+Wt5skXFKcyUVjWHWRtj0b/x9ZRAeuT9XsY ZzttEjZNGRyOBc1iWkSl3buUhmGDP7rcMe9DXKMPqGdTYQWqRNhkSmnPcIXYQFGbPjjh imGE2suIEVWZ/3R2h0k3/p1xkWSCpBWC4y8wF6RoARH/yAMyigjHxWUhs/40bKcaT0qt sovuRlphzi+A0yx3tnLDHFIxD2bR8DBQK+8F5jW4le5KsZLIuGqzpmVc18doTN4qspY4 hiiq9gGLPDbx8dxoAGkZFSS5rQUyV5z5PqpbQRP6pC5bS1vEmozpzgPGQ9eY7/4/Zo0o SIUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=HadI2W3r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t28si18283577edc.476.2021.10.17.21.36.07; Sun, 17 Oct 2021 21:36:30 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@marvell.com header.s=pfpt0220 header.b=HadI2W3r; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=REJECT dis=NONE) header.from=marvell.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230145AbhJREXB (ORCPT + 99 others); Mon, 18 Oct 2021 00:23:01 -0400 Received: from mx0a-0016f401.pphosted.com ([67.231.148.174]:20016 "EHLO mx0b-0016f401.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S229682AbhJREXA (ORCPT ); Mon, 18 Oct 2021 00:23:00 -0400 Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.16.1.2/8.16.1.2) with SMTP id 19I3nRpD024158; Sun, 17 Oct 2021 21:20:37 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-type; s=pfpt0220; bh=fvwR23mhzoQ7xeungNzFzAcwJdDvCK9RNiPfd9p2NFQ=; b=HadI2W3rvFOnPaVgXQ6u5tQIXnWrjgaXP2oIxYZgMDEzNGsQAp521m4Sa01J2A0q6D42 tQP1tAre9bJOzsdNHrO35Pw7DRre+9s4F3s5HdNRK2IZ80zbLDIwkGYVVWuLegBXSLQk mYTjx0E7wpi8ZbDKbACNY6hDCwgZ3dMKlJ+jy7bXbbgskYI1aR6EWDURIg5OLTGG0VI3 X7Suxcjb1iiGyA4W54pHBMsP49vGkBf5GWSUKve3SGdu+RE60gqTdcyDeAz5Ev+BY+M+ l7XxUwjvWd2T31ffw/0kWI/UrGHuUMV9nggyIUYCn0UOA5CEXINE2iPE9TN2mvJxy1yt VQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com with ESMTP id 3bs1bug2n9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 17 Oct 2021 21:20:37 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Sun, 17 Oct 2021 21:20:36 -0700 Received: from bbhushan2.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend Transport; Sun, 17 Oct 2021 21:20:32 -0700 From: Bharat Bhushan To: , , , , , , , CC: Bharat Bhushan Subject: [PATCH v5 3/4] perf/marvell: cn10k DDR perfmon event overflow handling Date: Mon, 18 Oct 2021 09:50:14 +0530 Message-ID: <20211018042015.25151-4-bbhushan2@marvell.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20211018042015.25151-1-bbhushan2@marvell.com> References: <20211018042015.25151-1-bbhushan2@marvell.com> MIME-Version: 1.0 Content-Type: text/plain X-Proofpoint-GUID: QumUeaGvxS3Bg2c6aP2amwmhd8DdkmCp X-Proofpoint-ORIG-GUID: QumUeaGvxS3Bg2c6aP2amwmhd8DdkmCp X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.182.1,Aquarius:18.0.790,Hydra:6.0.425,FMLib:17.0.607.475 definitions=2021-10-18_01,2021-10-14_02,2020-04-07_01 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org CN10k DSS h/w perfmon does not support event overflow interrupt, so periodic timer is being used. Each event counter is 48bit, which in worst case scenario can increment at maximum 5.6 GT/s. At this rate it may take many hours to overflow these counters. Therefore polling period for overflow is set to 100 sec, which can be changed using sysfs parameter. Two fixed event counters starts counting from zero on overflow, so overflow condition is when new count less than previous count. While eight programmable event counters freezes at maximum value. Also individual counter cannot be restarted, so need to restart all eight counters. Signed-off-by: Bharat Bhushan --- v3->v4->v5: - No Change v2->v3: - uintXX_t -> uXX v1->v2: - No Change drivers/perf/marvell_cn10k_ddr_pmu.c | 111 +++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/drivers/perf/marvell_cn10k_ddr_pmu.c b/drivers/perf/marvell_cn10k_ddr_pmu.c index 9b6d5e716b94..21fccb9090c5 100644 --- a/drivers/perf/marvell_cn10k_ddr_pmu.c +++ b/drivers/perf/marvell_cn10k_ddr_pmu.c @@ -11,6 +11,7 @@ #include #include #include +#include /* Performance Counters Operating Mode Control Registers */ #define DDRC_PERF_CNT_OP_MODE_CTRL 0x8020 @@ -127,6 +128,7 @@ struct cn10k_ddr_pmu { struct device *dev; int active_events; struct perf_event *events[DDRC_PERF_NUM_COUNTERS]; + struct hrtimer hrtimer; }; #define to_cn10k_ddr_pmu(p) container_of(p, struct cn10k_ddr_pmu, pmu) @@ -251,6 +253,18 @@ static const struct attribute_group *cn10k_attr_groups[] = { NULL, }; +/* Default poll timeout is 100 sec, which is very sufficient for + * 48 bit counter incremented max at 5.6 GT/s, which may take many + * hours to overflow. + */ +static unsigned long cn10k_ddr_pmu_poll_period_sec = 100; +module_param_named(poll_period_sec, cn10k_ddr_pmu_poll_period_sec, ulong, 0644); + +static ktime_t cn10k_ddr_pmu_timer_period(void) +{ + return ms_to_ktime((u64)cn10k_ddr_pmu_poll_period_sec * USEC_PER_SEC); +} + static int ddr_perf_get_event_bitmap(int eventid, u64 *event_bitmap) { switch (eventid) { @@ -433,6 +447,10 @@ static int cn10k_ddr_perf_event_add(struct perf_event *event, int flags) pmu->active_events++; hwc->idx = counter; + if (pmu->active_events == 1) + hrtimer_start(&pmu->hrtimer, cn10k_ddr_pmu_timer_period(), + HRTIMER_MODE_REL_PINNED); + if (counter < DDRC_PERF_NUM_GEN_COUNTERS) { /* Generic counters, configure event id */ reg_offset = DDRC_PERF_CFG(counter); @@ -484,6 +502,10 @@ static void cn10k_ddr_perf_event_del(struct perf_event *event, int flags) cn10k_ddr_perf_free_counter(pmu, counter); pmu->active_events--; hwc->idx = -1; + + /* Cancel timer when no events to capture */ + if (pmu->active_events == 0) + hrtimer_cancel(&pmu->hrtimer); } static void cn10k_ddr_perf_pmu_enable(struct pmu *pmu) @@ -502,6 +524,92 @@ static void cn10k_ddr_perf_pmu_disable(struct pmu *pmu) DDRC_PERF_CNT_END_OP_CTRL); } +static void cn10k_ddr_perf_event_update_all(struct cn10k_ddr_pmu *pmu) +{ + struct hw_perf_event *hwc; + int i; + + for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) { + if (pmu->events[i] == NULL) + continue; + + cn10k_ddr_perf_event_update(pmu->events[i]); + } + + /* Reset previous count as h/w counter are reset */ + for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) { + if (pmu->events[i] == NULL) + continue; + + hwc = &pmu->events[i]->hw; + local64_set(&hwc->prev_count, 0); + } +} + +static irqreturn_t cn10k_ddr_pmu_overflow_handler(struct cn10k_ddr_pmu *pmu) +{ + struct perf_event *event; + struct hw_perf_event *hwc; + u64 prev_count, new_count; + u64 value; + int i; + + event = pmu->events[DDRC_PERF_READ_COUNTER_IDX]; + if (event) { + hwc = &event->hw; + prev_count = local64_read(&hwc->prev_count); + new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx); + + /* Overflow condition is when new count less than + * previous count + */ + if (new_count < prev_count) + cn10k_ddr_perf_event_update(event); + } + + event = pmu->events[DDRC_PERF_WRITE_COUNTER_IDX]; + if (event) { + hwc = &event->hw; + prev_count = local64_read(&hwc->prev_count); + new_count = cn10k_ddr_perf_read_counter(pmu, hwc->idx); + + /* Overflow condition is when new count less than + * previous count + */ + if (new_count < prev_count) + cn10k_ddr_perf_event_update(event); + } + + for (i = 0; i < DDRC_PERF_NUM_GEN_COUNTERS; i++) { + if (pmu->events[i] == NULL) + continue; + + value = cn10k_ddr_perf_read_counter(pmu, i); + if (value == DDRC_PERF_CNT_MAX_VALUE) { + pr_info("Counter-(%d) reached max value\n", i); + cn10k_ddr_perf_event_update_all(pmu); + cn10k_ddr_perf_pmu_disable(&pmu->pmu); + cn10k_ddr_perf_pmu_enable(&pmu->pmu); + } + } + + return IRQ_HANDLED; +} + +static enum hrtimer_restart cn10k_ddr_pmu_timer_handler(struct hrtimer *hrtimer) +{ + struct cn10k_ddr_pmu *pmu = container_of(hrtimer, struct cn10k_ddr_pmu, + hrtimer); + unsigned long flags; + + local_irq_save(flags); + cn10k_ddr_pmu_overflow_handler(pmu); + local_irq_restore(flags); + + hrtimer_forward_now(hrtimer, cn10k_ddr_pmu_timer_period()); + return HRTIMER_RESTART; +} + static int cn10k_ddr_perf_probe(struct platform_device *pdev) { struct cn10k_ddr_pmu *ddr_pmu; @@ -550,6 +658,9 @@ static int cn10k_ddr_perf_probe(struct platform_device *pdev) if (!name) return -ENOMEM; + hrtimer_init(&ddr_pmu->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + ddr_pmu->hrtimer.function = cn10k_ddr_pmu_timer_handler; + ret = perf_pmu_register(&ddr_pmu->pmu, name, -1); if (ret) return ret; -- 2.17.1