From patchwork Fri Mar 10 06:28:45 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anurup M X-Patchwork-Id: 9615141 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 43E3960417 for ; Fri, 10 Mar 2017 06:31:41 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 346A7286F6 for ; Fri, 10 Mar 2017 06:31:41 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 279EE286FB; Fri, 10 Mar 2017 06:31:41 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, DKIM_VALID, FREEMAIL_FROM autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 18CB4286F6 for ; Fri, 10 Mar 2017 06:31:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=VhiS7PsfpeagEW8mU3hWbtn+qHEX92ga1ENDhyeudgo=; b=FK1 TD78fS/trv1t6aVBdhxzDh7ZGuCrfiBO1+4XsUGP1Ugto+/xqXRGz/eS/oUc9ZUUCJ+8+a0mO/Ob5 tAtFO63voUsW5zu+1Goo/VuirfmqlvzyzrhZgfCS86VCS7zMSCYuPuyGcUTPNIqPqJZNHV6BVV64T LiHJN3ScX6136RefQXC+DILCBDO6Dr1j51QqAl9KKbU7BUs0I6hRfGCTk0bE9koNzeOR/7It8U0xy kUbdSGq1LXJKxmbc2if4BfeU/dbTcLC3xWpOYzvN3GiZOJrsLuuHsjw96jITTxYyEwCIU/MX9sijW QDoDiK5LTYp0hGurTcFjkeUtOCXmRjQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cmE5T-0003lO-4x; Fri, 10 Mar 2017 06:31:39 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cmE3A-00017P-Gu for linux-arm-kernel@bombadil.infradead.org; Fri, 10 Mar 2017 06:29:16 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=Message-Id:Date:Subject:Cc:To:From: Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=0ehn31qo2BnzhOzeOTW/FryChRm8oabOyMqx8uAimdg=; b=K0JVCnQgRPeC+2/+E4nKDtKru ZNGkX4xsPLP9sJw+nQGp4I698w0fDlkHYIk1b5JEpemAFwesufxkinczWjlZG8fnKz9sPB31nes11 nPGr3Sygv/9xLCapfO3Yuq1BdvAOTmXjfSrP4qJiqEg5eTh9X7xI4ojBQvUW/ODPMdchTRwLg1r5X LY1J+tD1vR1eS7qkRG7w8ZWZmHI11z5c4R6Nyn/GO13ckMGF4kw2lq/BXMVKWAJlpBR9EW13VNB+r m7urN/JVbhbLUUvBzExSMK28uLouQQ+tzBAFgvI8pMUgOWE+wTUB40EuOtN5C9JQbOK5u7qcmyFAl uPXD230sw==; Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cmE37-00078U-VE for linux-arm-kernel@lists.infradead.org; Fri, 10 Mar 2017 06:29:15 +0000 Received: by mail-pf0-x241.google.com with SMTP id v190so9736265pfb.0 for ; Thu, 09 Mar 2017 22:28:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=0ehn31qo2BnzhOzeOTW/FryChRm8oabOyMqx8uAimdg=; b=iZwIB0a4h6saEb3p0VYPWtU/hM4W6S5wTkdJrqljbxqhUxQQARXBo9++UZFyDLuVZV ml/Tq2IUYrenh9Zn9HlRzVFGkkgneIOY3hCP90OE7UuLmhxxjuc3KdSqVio7l8VtKKqE p5zSvLP1MATygpGcrG77QlSizt6qfPsJR3Romv37ET7UeqCx23E7RzqJXwNG/qXEkG/F bPwyHx3e3PRigbLqjf9sfkNMgBgCX6wiceqe8loRCDoNhwdT0SA/tlC9wftLow3wHZmZ Qas+XQk7DJjt/yVYxqm+ZgjM+/+jZTTRt1oGT4Kl5s0jxqO7Ahw2FNiMt8kBvAY6mgFR MdeA== 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; bh=0ehn31qo2BnzhOzeOTW/FryChRm8oabOyMqx8uAimdg=; b=QlPsJ5DjJla1RqcTCeVNRaUVhUX4OtuN45JuSNzeXgM1WYE8S7Xn+lrsOeR8A02KC2 ODx2i3wsvdC4EkAttm+j+T94+G9vXuUnVjYG0/EpUV9BKRfhK1wY9CJPLoF0M61Gl8Kl qFpPZyBwFi7GrK6QRyaHtL7jqu0cdX7E70iIbk9iECl3XCao/pDB/0Y8xuqJV1RQtZRg ri+0MYhMGrC7wtGvxLPn/M+g3XXeepyHS1FvJdlxas6nUQSCUNnMZ92wxSyLV1diOU93 0T9+Y2NlWd7tyVUCiDYw+6XXHAPQY8jO9duOEbPZvqpvQ4TprgYjjGkXN4Of18+r16hj 7VUQ== X-Gm-Message-State: AMke39kIBqkFSQcEVCf0/AdhkHa0kTcxnGCx5+xk6hqmeE1W73tLRAk3e1q6T5LQHyg/Kw== X-Received: by 10.84.225.146 with SMTP id u18mr23307897plj.157.1489127332893; Thu, 09 Mar 2017 22:28:52 -0800 (PST) Received: from localhost.localdomain ([14.141.5.98]) by smtp.gmail.com with ESMTPSA id s12sm16116445pfj.9.2017.03.09.22.28.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 09 Mar 2017 22:28:52 -0800 (PST) From: Anurup M X-Google-Original-From: Anurup M To: mark.rutland@arm.com, will.deacon@arm.com Subject: [PATCH v6 08/11] drivers: perf: hisi: use poll method to avoid L3C counter overflow Date: Fri, 10 Mar 2017 01:28:45 -0500 Message-Id: <1489127325-112821-1-git-send-email-anurup.m@huawei.com> X-Mailer: git-send-email 2.1.4 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170310_012914_201541_980960A7 X-CRM114-Status: GOOD ( 22.35 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dikshit.n@huawei.com, shyju.pv@huawei.com, anurupvasu@gmail.com, gabriele.paoloni@huawei.com, huangdaode@hisilicon.com, john.garry@huawei.com, linux-kernel@vger.kernel.org, xuwei5@hisilicon.com, linuxarm@huawei.com, zhangshaokun@hisilicon.com, sanil.kumar@hisilicon.com, linux-arm-kernel@lists.infradead.org, shiju.jose@huawei.com, tanxiaojun@huawei.com, anurup.m@huawei.com MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Add hrtimer support which use poll method to avoid counter overflow when overflow IRQ is not supported in hardware. The L3 cache PMU use N-N SPI interrupt which has no support in kernel mainline. So use hrtimer to poll and update event counter to avoid overflow condition for L3 cache PMU. An interval of 10 seconds is used for the hrtimer. Signed-off-by: Dikshit N Signed-off-by: Anurup M --- drivers/perf/hisilicon/hisi_uncore_l3c.c | 47 ++++++++++++++++++ drivers/perf/hisilicon/hisi_uncore_pmu.c | 82 ++++++++++++++++++++++++++++++++ drivers/perf/hisilicon/hisi_uncore_pmu.h | 17 +++++++ 3 files changed, 146 insertions(+) diff --git a/drivers/perf/hisilicon/hisi_uncore_l3c.c b/drivers/perf/hisilicon/hisi_uncore_l3c.c index 7f80d07..f23fbc2 100644 --- a/drivers/perf/hisilicon/hisi_uncore_l3c.c +++ b/drivers/perf/hisilicon/hisi_uncore_l3c.c @@ -20,6 +20,8 @@ * along with this program. If not, see . */ #include +#include +#include #include #include #include @@ -53,6 +55,22 @@ enum armv8_hisi_l3c_counters { #define L3C_CNT0_REG_OFF 0x170 #define L3C_EVENT_EN 0x1000000 +/* + * Default timer frequency to poll and avoid counter overflow. + * CPU speed = 2.4Ghz, Therefore Access time = 0.4ns + * L1 cache - 2 way set associative + * L2 - 16 way set associative + * L3 - 16 way set associative. L3 cache has 4 banks. + * + * Overflow time = 2^31 * (access time L1 + access time L2 + access time L3) + * = 2^31 * ((2 * 0.4ns) + (16 * 0.4ns) + (4 * 16 * 0.4ns)) = 70 seconds + * + * L3 cache is also used by devices like PCIe, SAS etc. at + * the same time. So the overflow time could be even smaller. + * So on a safe side we use a timer interval of 10sec + */ +#define L3C_HRTIMER_INTERVAL (10LL * MSEC_PER_SEC) + #define GET_MODULE_ID(hwmod_data) hwmod_data->l3c_hwcfg.module_id #define GET_BANK_SEL(hwmod_data) hwmod_data->l3c_hwcfg.bank_select @@ -474,11 +492,24 @@ static const struct attribute_group hisi_l3c_cpumask_attr_group = { .attrs = hisi_l3c_cpumask_attrs, }; +static DEVICE_ATTR(hrtimer_interval, 0444, hisi_hrtimer_interval_sysfs_show, + NULL); + +static struct attribute *hisi_l3c_hrtimer_interval_attrs[] = { + &dev_attr_hrtimer_interval.attr, + NULL, +}; + +static const struct attribute_group hisi_l3c_hrtimer_interval_attr_group = { + .attrs = hisi_l3c_hrtimer_interval_attrs, +}; + static const struct attribute_group *hisi_l3c_pmu_attr_groups[] = { &hisi_l3c_attr_group, &hisi_l3c_format_group, &hisi_l3c_events_group, &hisi_l3c_cpumask_attr_group, + &hisi_l3c_hrtimer_interval_attr_group, NULL, }; @@ -494,6 +525,15 @@ static struct hisi_uncore_ops hisi_uncore_l3c_ops = { .write_counter = hisi_l3c_write_counter, }; +/* Initialize hrtimer to poll for avoiding counter overflow */ +static void hisi_l3c_hrtimer_init(struct hisi_pmu *l3c_pmu) +{ + INIT_LIST_HEAD(&l3c_pmu->active_list); + l3c_pmu->ops->start_hrtimer = hisi_hrtimer_start; + l3c_pmu->ops->stop_hrtimer = hisi_hrtimer_stop; + hisi_hrtimer_init(l3c_pmu, L3C_HRTIMER_INTERVAL); +} + static int hisi_l3c_pmu_init(struct hisi_pmu *l3c_pmu, struct hisi_djtag_client *client) { @@ -503,6 +543,7 @@ static int hisi_l3c_pmu_init(struct hisi_pmu *l3c_pmu, l3c_pmu->num_events = HISI_HWEVENT_L3C_EVENT_MAX; l3c_pmu->num_counters = HISI_IDX_L3C_COUNTER_MAX; + l3c_pmu->num_active = 0; l3c_pmu->scl_id = hisi_djtag_get_sclid(client); l3c_pmu->name = kasprintf(GFP_KERNEL, "hisi_l3c%u_%u", @@ -513,6 +554,12 @@ static int hisi_l3c_pmu_init(struct hisi_pmu *l3c_pmu, /* Pick one core to use for cpumask attributes */ cpumask_set_cpu(smp_processor_id(), &l3c_pmu->cpu); + /* + * Use poll method to avoid counter overflow as overflow IRQ + * is not supported in v1,v2 hardware. + */ + hisi_l3c_hrtimer_init(l3c_pmu); + return 0; } diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisilicon/hisi_uncore_pmu.c index 0e7b5f1..787602b 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c @@ -65,6 +65,70 @@ ssize_t hisi_cpumask_sysfs_show(struct device *dev, return cpumap_print_to_pagebuf(true, buf, &hisi_pmu->cpu); } +/* + * sysfs hrtimer_interval attributes + */ +ssize_t hisi_hrtimer_interval_sysfs_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct pmu *pmu = dev_get_drvdata(dev); + struct hisi_pmu *hisi_pmu = to_hisi_pmu(pmu); + + if (hisi_pmu->hrt_duration) + return sprintf(buf, "%llu\n", hisi_pmu->hrt_duration); + return 0; +} + +/* The counter overflow IRQ is not supported for some PMUs + * use hrtimer to periodically poll and avoid overflow + */ +static enum hrtimer_restart hisi_hrtimer_callback(struct hrtimer *hrtimer) +{ + struct hisi_pmu *hisi_pmu = container_of(hrtimer, + struct hisi_pmu, hrtimer); + struct perf_event *event; + struct hw_perf_event *hwc; + unsigned long flags; + + /* Return if no active events */ + if (!hisi_pmu->num_active) + return HRTIMER_NORESTART; + + local_irq_save(flags); + + /* Update event count for each active event */ + list_for_each_entry(event, &hisi_pmu->active_list, active_entry) { + hwc = &event->hw; + /* Read hardware counter and update the Perf event counter */ + hisi_pmu->ops->event_update(event, hwc, GET_CNTR_IDX(hwc)); + } + + local_irq_restore(flags); + hrtimer_forward_now(hrtimer, ms_to_ktime(hisi_pmu->hrt_duration)); + return HRTIMER_RESTART; +} + +void hisi_hrtimer_init(struct hisi_pmu *hisi_pmu, u64 timer_interval) +{ + /* hr timer clock initalization */ + hrtimer_init(&hisi_pmu->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hisi_pmu->hrtimer.function = &hisi_hrtimer_callback; + hisi_pmu->hrt_duration = timer_interval; +} + +void hisi_hrtimer_start(struct hisi_pmu *hisi_pmu) +{ + hrtimer_start(&hisi_pmu->hrtimer, + ms_to_ktime(hisi_pmu->hrt_duration), + HRTIMER_MODE_REL_PINNED); +} + +void hisi_hrtimer_stop(struct hisi_pmu *hisi_pmu) +{ + hrtimer_cancel(&hisi_pmu->hrtimer); +} + /* djtag read interface - Call djtag driver to access SoC registers */ int hisi_djtag_readreg(int module_id, int bank, u32 offset, struct hisi_djtag_client *client, u32 *value) @@ -266,6 +330,15 @@ void hisi_uncore_pmu_start(struct perf_event *event, int flags) (u32) prev_raw_count); } + /* Start hrtimer when the first event is started in this PMU */ + if (hisi_pmu->ops->start_hrtimer) { + hisi_pmu->num_active++; + list_add_tail(&event->active_entry, &hisi_pmu->active_list); + + if (hisi_pmu->num_active == 1) + hisi_pmu->ops->start_hrtimer(hisi_pmu); + } + hisi_uncore_pmu_enable_event(event); perf_event_update_userpage(event); } @@ -279,6 +352,15 @@ void hisi_uncore_pmu_stop(struct perf_event *event, int flags) WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED); hwc->state |= PERF_HES_STOPPED; + /* Stop hrtimer when the last event is stopped in this PMU */ + if (hisi_pmu->ops->stop_hrtimer) { + hisi_pmu->num_active--; + list_del(&event->active_entry); + + if (hisi_pmu->num_active == 0) + hisi_pmu->ops->stop_hrtimer(hisi_pmu); + } + if (hwc->state & PERF_HES_UPTODATE) return; diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h index 14b8c53..1b1f08e 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h @@ -79,13 +79,20 @@ struct hisi_uncore_ops { void (*disable_counter)(struct hisi_pmu *, int); void (*start_counters)(struct hisi_pmu *); void (*stop_counters)(struct hisi_pmu *); + void (*start_hrtimer)(struct hisi_pmu *); + void (*stop_hrtimer)(struct hisi_pmu *); }; /* Generic pmu struct for different pmu types */ struct hisi_pmu { const char *name; struct perf_event **hw_perf_events; + struct list_head active_list; /* Active events list */ struct hisi_uncore_ops *ops; + struct hrtimer hrtimer; /* hrtimer to handle the + * counter overflow + */ + u64 hrt_duration; /* hrtimer timeout */ struct device *dev; void *hwmod_data; /* Hardware module specific data */ cpumask_t cpu; @@ -94,6 +101,7 @@ struct hisi_pmu { u32 scl_id; int num_counters; int num_events; + int num_active; }; void hisi_uncore_pmu_read(struct perf_event *event); @@ -113,6 +121,15 @@ ssize_t hisi_format_sysfs_show(struct device *dev, struct device_attribute *attr, char *buf); ssize_t hisi_cpumask_sysfs_show(struct device *dev, struct device_attribute *attr, char *buf); +ssize_t hisi_hrtimer_interval_sysfs_show(struct device *dev, + struct device_attribute *attr, + char *buf); +ssize_t hisi_hrtimer_interval_sysfs_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count); +void hisi_hrtimer_init(struct hisi_pmu *hisi_pmu, u64 timer_interval); +void hisi_hrtimer_start(struct hisi_pmu *hisi_pmu); +void hisi_hrtimer_stop(struct hisi_pmu *hisi_pmu); int hisi_djtag_readreg(int module_id, int bank, u32 offset, struct hisi_djtag_client *client, u32 *value); int hisi_djtag_writereg(int module_id, int bank, u32 offset,