From nobody Thu Oct 9 06:56:23 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ECB8624E4DD for ; Thu, 19 Jun 2025 12:56:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; cv=none; b=sASV7qL/6ykBcM47+kSqYKVSIBm2cOqvSDT3mnzCqXVrrA8WtW247l2TbAU0oyI8R1DwZiIoTrbB36fs8i2Uw8ZwDfcvysvzYkbJ2alRWg+/e4hxCBW5TthVk0PztwIoIHNn+H6O8zY3MewbuJd/2tKvONxMuIgbONN3uucrZ0U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; c=relaxed/simple; bh=Vo9Su6WecOC161havJMXdjSYOQkpzresUTlZBj6b5MA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=XNi8fTVc9pqmqw2wZrEB79GOsG3tuB25XlTLDM98mspRE/OFn+YCQjuPzEmN946jzVLovq/Djl8AvXsU1eKzIBGYTvrX4K+FDGwNHBm2gZZ4QSq+chS61eLhYe2fj/bGJdFQw59Ff1bsAIs8xoR+blBIuWK/DHlGCZ2ov4pHyX4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4bNLDG4wzZzVmcR; Thu, 19 Jun 2025 20:54:54 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id DA8251400D9; Thu, 19 Jun 2025 20:56:04 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:04 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:03 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 1/8] drivers/perf: hisi: Simplify the probe process for each DDRC version Date: Thu, 19 Jun 2025 20:55:50 +0800 Message-ID: <20250619125557.57372-2-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He Version 1 and 2 of DDRC PMU also use different HID. Make use of struct acpi_device_id::driver_data for version specific information rather than judge the version register. This will help to simplify the probe process and also a bit easier for extension. In order to support this extend struct hisi_pmu_dev_info for version specific counter bits and event range. Signed-off-by: Junhao He Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 328 ++++++++---------- drivers/perf/hisilicon/hisi_uncore_pmu.h | 2 + 2 files changed, 142 insertions(+), 188 deletions(-) diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_ddrc_pmu.c index 7e490f8868f2..7e3c2436e96b 100644 --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c @@ -50,6 +50,10 @@ #define DDRC_V1_NR_EVENTS 0x7 #define DDRC_V2_NR_EVENTS 0x90 =20 +#define DDRC_EVENT_CNTn(base, n) ((base) + (n) * 8) +#define DDRC_EVENT_TYPEn(base, n) ((base) + (n) * 4) +#define DDRC_UNIMPLEMENTED_REG GENMASK(31, 0) + /* * For PMU v1, there are eight-events and every event has been mapped * to fixed-purpose counters which register offset is not consistent. @@ -63,47 +67,37 @@ static const u32 ddrc_reg_off[] =3D { DDRC_PRE_CMD, DDRC_ACT_CMD, DDRC_RNK_CHG, DDRC_RW_CHG }; =20 -/* - * Select the counter register offset using the counter index. - * In PMU v1, there are no programmable counter, the count - * is read form the statistics counter register itself. - */ -static u32 hisi_ddrc_pmu_v1_get_counter_offset(int cntr_idx) -{ - return ddrc_reg_off[cntr_idx]; -} - -static u32 hisi_ddrc_pmu_v2_get_counter_offset(int cntr_idx) -{ - return DDRC_V2_EVENT_CNT + cntr_idx * 8; -} +struct hisi_ddrc_pmu_regs { + u32 event_cnt; + u32 event_ctrl; + u32 event_type; + u32 perf_ctrl; + u32 perf_ctrl_en; + u32 int_mask; + u32 int_clear; + u32 int_status; +}; =20 -static u64 hisi_ddrc_pmu_v1_read_counter(struct hisi_pmu *ddrc_pmu, +static u64 hisi_ddrc_pmu_read_counter(struct hisi_pmu *ddrc_pmu, struct hw_perf_event *hwc) { - return readl(ddrc_pmu->base + - hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx)); -} + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; =20 -static void hisi_ddrc_pmu_v1_write_counter(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc, u64 val) -{ - writel((u32)val, - ddrc_pmu->base + hisi_ddrc_pmu_v1_get_counter_offset(hwc->idx)); -} + if (regs->event_cnt =3D=3D DDRC_UNIMPLEMENTED_REG) + return readl(ddrc_pmu->base + ddrc_reg_off[hwc->idx]); =20 -static u64 hisi_ddrc_pmu_v2_read_counter(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) -{ - return readq(ddrc_pmu->base + - hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx)); + return readq(ddrc_pmu->base + DDRC_EVENT_CNTn(regs->event_cnt, hwc->idx)); } =20 -static void hisi_ddrc_pmu_v2_write_counter(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc, u64 val) +static void hisi_ddrc_pmu_write_counter(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc, u64 val) { - writeq(val, - ddrc_pmu->base + hisi_ddrc_pmu_v2_get_counter_offset(hwc->idx)); + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; + + if (regs->event_cnt =3D=3D DDRC_UNIMPLEMENTED_REG) + writel((u32)val, ddrc_pmu->base + ddrc_reg_off[hwc->idx]); + else + writeq(val, ddrc_pmu->base + DDRC_EVENT_CNTn(regs->event_cnt, hwc->idx)); } =20 /* @@ -114,54 +108,12 @@ static void hisi_ddrc_pmu_v2_write_counter(struct his= i_pmu *ddrc_pmu, static void hisi_ddrc_pmu_write_evtype(struct hisi_pmu *ddrc_pmu, int idx, u32 type) { - u32 offset; - - if (ddrc_pmu->identifier >=3D HISI_PMU_V2) { - offset =3D DDRC_V2_EVENT_TYPE + 4 * idx; - writel(type, ddrc_pmu->base + offset); - } -} - -static void hisi_ddrc_pmu_v1_start_counters(struct hisi_pmu *ddrc_pmu) -{ - u32 val; + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; =20 - /* Set perf_enable in DDRC_PERF_CTRL to start event counting */ - val =3D readl(ddrc_pmu->base + DDRC_PERF_CTRL); - val |=3D DDRC_V1_PERF_CTRL_EN; - writel(val, ddrc_pmu->base + DDRC_PERF_CTRL); -} + if (regs->event_type =3D=3D DDRC_UNIMPLEMENTED_REG) + return; =20 -static void hisi_ddrc_pmu_v1_stop_counters(struct hisi_pmu *ddrc_pmu) -{ - u32 val; - - /* Clear perf_enable in DDRC_PERF_CTRL to stop event counting */ - val =3D readl(ddrc_pmu->base + DDRC_PERF_CTRL); - val &=3D ~DDRC_V1_PERF_CTRL_EN; - writel(val, ddrc_pmu->base + DDRC_PERF_CTRL); -} - -static void hisi_ddrc_pmu_v1_enable_counter(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) -{ - u32 val; - - /* Set counter index(event code) in DDRC_EVENT_CTRL register */ - val =3D readl(ddrc_pmu->base + DDRC_EVENT_CTRL); - val |=3D (1 << GET_DDRC_EVENTID(hwc)); - writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL); -} - -static void hisi_ddrc_pmu_v1_disable_counter(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) -{ - u32 val; - - /* Clear counter index(event code) in DDRC_EVENT_CTRL register */ - val =3D readl(ddrc_pmu->base + DDRC_EVENT_CTRL); - val &=3D ~(1 << GET_DDRC_EVENTID(hwc)); - writel(val, ddrc_pmu->base + DDRC_EVENT_CTRL); + writel(type, ddrc_pmu->base + DDRC_EVENT_TYPEn(regs->event_type, idx)); } =20 static int hisi_ddrc_pmu_v1_get_event_idx(struct perf_event *event) @@ -180,120 +132,96 @@ static int hisi_ddrc_pmu_v1_get_event_idx(struct per= f_event *event) return idx; } =20 -static int hisi_ddrc_pmu_v2_get_event_idx(struct perf_event *event) +static int hisi_ddrc_pmu_get_event_idx(struct perf_event *event) { + struct hisi_pmu *ddrc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; + + if (regs->event_type =3D=3D DDRC_UNIMPLEMENTED_REG) + return hisi_ddrc_pmu_v1_get_event_idx(event); + return hisi_uncore_pmu_get_event_idx(event); } =20 -static void hisi_ddrc_pmu_v2_start_counters(struct hisi_pmu *ddrc_pmu) +static void hisi_ddrc_pmu_start_counters(struct hisi_pmu *ddrc_pmu) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL); - val |=3D DDRC_V2_PERF_CTRL_EN; - writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL); + val =3D readl(ddrc_pmu->base + regs->perf_ctrl); + val |=3D regs->perf_ctrl_en; + writel(val, ddrc_pmu->base + regs->perf_ctrl); } =20 -static void hisi_ddrc_pmu_v2_stop_counters(struct hisi_pmu *ddrc_pmu) +static void hisi_ddrc_pmu_stop_counters(struct hisi_pmu *ddrc_pmu) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_PERF_CTRL); - val &=3D ~DDRC_V2_PERF_CTRL_EN; - writel(val, ddrc_pmu->base + DDRC_V2_PERF_CTRL); + val =3D readl(ddrc_pmu->base + regs->perf_ctrl); + val &=3D ~regs->perf_ctrl_en; + writel(val, ddrc_pmu->base + regs->perf_ctrl); } =20 -static void hisi_ddrc_pmu_v2_enable_counter(struct hisi_pmu *ddrc_pmu, +static void hisi_ddrc_pmu_enable_counter(struct hisi_pmu *ddrc_pmu, struct hw_perf_event *hwc) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL); - val |=3D 1 << hwc->idx; - writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL); + val =3D readl(ddrc_pmu->base + regs->event_ctrl); + val |=3D BIT_ULL(hwc->idx); + writel(val, ddrc_pmu->base + regs->event_ctrl); } =20 -static void hisi_ddrc_pmu_v2_disable_counter(struct hisi_pmu *ddrc_pmu, +static void hisi_ddrc_pmu_disable_counter(struct hisi_pmu *ddrc_pmu, struct hw_perf_event *hwc) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_EVENT_CTRL); - val &=3D ~(1 << hwc->idx); - writel(val, ddrc_pmu->base + DDRC_V2_EVENT_CTRL); -} - -static void hisi_ddrc_pmu_v1_enable_counter_int(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) -{ - u32 val; - - /* Write 0 to enable interrupt */ - val =3D readl(ddrc_pmu->base + DDRC_INT_MASK); - val &=3D ~(1 << hwc->idx); - writel(val, ddrc_pmu->base + DDRC_INT_MASK); -} - -static void hisi_ddrc_pmu_v1_disable_counter_int(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) -{ - u32 val; - - /* Write 1 to mask interrupt */ - val =3D readl(ddrc_pmu->base + DDRC_INT_MASK); - val |=3D 1 << hwc->idx; - writel(val, ddrc_pmu->base + DDRC_INT_MASK); + val =3D readl(ddrc_pmu->base + regs->event_ctrl); + val &=3D ~BIT_ULL(hwc->idx); + writel(val, ddrc_pmu->base + regs->event_ctrl); } =20 -static void hisi_ddrc_pmu_v2_enable_counter_int(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) +static void hisi_ddrc_pmu_enable_counter_int(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_INT_MASK); - val &=3D ~(1 << hwc->idx); - writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK); + val =3D readl(ddrc_pmu->base + regs->int_mask); + val &=3D ~BIT_ULL(hwc->idx); + writel(val, ddrc_pmu->base + regs->int_mask); } =20 -static void hisi_ddrc_pmu_v2_disable_counter_int(struct hisi_pmu *ddrc_pmu, - struct hw_perf_event *hwc) +static void hisi_ddrc_pmu_disable_counter_int(struct hisi_pmu *ddrc_pmu, + struct hw_perf_event *hwc) { + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; u32 val; =20 - val =3D readl(ddrc_pmu->base + DDRC_V2_INT_MASK); - val |=3D 1 << hwc->idx; - writel(val, ddrc_pmu->base + DDRC_V2_INT_MASK); + val =3D readl(ddrc_pmu->base + regs->int_mask); + val |=3D BIT_ULL(hwc->idx); + writel(val, ddrc_pmu->base + regs->int_mask); } =20 -static u32 hisi_ddrc_pmu_v1_get_int_status(struct hisi_pmu *ddrc_pmu) +static u32 hisi_ddrc_pmu_get_int_status(struct hisi_pmu *ddrc_pmu) { - return readl(ddrc_pmu->base + DDRC_INT_STATUS); -} + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; =20 -static void hisi_ddrc_pmu_v1_clear_int_status(struct hisi_pmu *ddrc_pmu, - int idx) -{ - writel(1 << idx, ddrc_pmu->base + DDRC_INT_CLEAR); + return readl(ddrc_pmu->base + regs->int_status); } =20 -static u32 hisi_ddrc_pmu_v2_get_int_status(struct hisi_pmu *ddrc_pmu) +static void hisi_ddrc_pmu_clear_int_status(struct hisi_pmu *ddrc_pmu, + int idx) { - return readl(ddrc_pmu->base + DDRC_V2_INT_STATUS); -} + struct hisi_ddrc_pmu_regs *regs =3D ddrc_pmu->dev_info->private; =20 -static void hisi_ddrc_pmu_v2_clear_int_status(struct hisi_pmu *ddrc_pmu, - int idx) -{ - writel(1 << idx, ddrc_pmu->base + DDRC_V2_INT_CLEAR); + writel(1 << idx, ddrc_pmu->base + regs->int_clear); } =20 -static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] =3D { - { "HISI0233", }, - { "HISI0234", }, - {} -}; -MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match); - static int hisi_ddrc_pmu_init_data(struct platform_device *pdev, struct hisi_pmu *ddrc_pmu) { @@ -314,6 +242,10 @@ static int hisi_ddrc_pmu_init_data(struct platform_dev= ice *pdev, return -EINVAL; } =20 + ddrc_pmu->dev_info =3D device_get_match_data(&pdev->dev); + if (!ddrc_pmu->dev_info) + return -ENODEV; + ddrc_pmu->base =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(ddrc_pmu->base)) { dev_err(&pdev->dev, "ioremap failed for ddrc_pmu resource\n"); @@ -396,34 +328,19 @@ static const struct attribute_group *hisi_ddrc_pmu_v2= _attr_groups[] =3D { NULL }; =20 -static const struct hisi_uncore_ops hisi_uncore_ddrc_v1_ops =3D { +static const struct hisi_uncore_ops hisi_uncore_ddrc_ops =3D { .write_evtype =3D hisi_ddrc_pmu_write_evtype, - .get_event_idx =3D hisi_ddrc_pmu_v1_get_event_idx, - .start_counters =3D hisi_ddrc_pmu_v1_start_counters, - .stop_counters =3D hisi_ddrc_pmu_v1_stop_counters, - .enable_counter =3D hisi_ddrc_pmu_v1_enable_counter, - .disable_counter =3D hisi_ddrc_pmu_v1_disable_counter, - .enable_counter_int =3D hisi_ddrc_pmu_v1_enable_counter_int, - .disable_counter_int =3D hisi_ddrc_pmu_v1_disable_counter_int, - .write_counter =3D hisi_ddrc_pmu_v1_write_counter, - .read_counter =3D hisi_ddrc_pmu_v1_read_counter, - .get_int_status =3D hisi_ddrc_pmu_v1_get_int_status, - .clear_int_status =3D hisi_ddrc_pmu_v1_clear_int_status, -}; - -static const struct hisi_uncore_ops hisi_uncore_ddrc_v2_ops =3D { - .write_evtype =3D hisi_ddrc_pmu_write_evtype, - .get_event_idx =3D hisi_ddrc_pmu_v2_get_event_idx, - .start_counters =3D hisi_ddrc_pmu_v2_start_counters, - .stop_counters =3D hisi_ddrc_pmu_v2_stop_counters, - .enable_counter =3D hisi_ddrc_pmu_v2_enable_counter, - .disable_counter =3D hisi_ddrc_pmu_v2_disable_counter, - .enable_counter_int =3D hisi_ddrc_pmu_v2_enable_counter_int, - .disable_counter_int =3D hisi_ddrc_pmu_v2_disable_counter_int, - .write_counter =3D hisi_ddrc_pmu_v2_write_counter, - .read_counter =3D hisi_ddrc_pmu_v2_read_counter, - .get_int_status =3D hisi_ddrc_pmu_v2_get_int_status, - .clear_int_status =3D hisi_ddrc_pmu_v2_clear_int_status, + .get_event_idx =3D hisi_ddrc_pmu_get_event_idx, + .start_counters =3D hisi_ddrc_pmu_start_counters, + .stop_counters =3D hisi_ddrc_pmu_stop_counters, + .enable_counter =3D hisi_ddrc_pmu_enable_counter, + .disable_counter =3D hisi_ddrc_pmu_disable_counter, + .enable_counter_int =3D hisi_ddrc_pmu_enable_counter_int, + .disable_counter_int =3D hisi_ddrc_pmu_disable_counter_int, + .write_counter =3D hisi_ddrc_pmu_write_counter, + .read_counter =3D hisi_ddrc_pmu_read_counter, + .get_int_status =3D hisi_ddrc_pmu_get_int_status, + .clear_int_status =3D hisi_ddrc_pmu_clear_int_status, }; =20 static int hisi_ddrc_pmu_dev_probe(struct platform_device *pdev, @@ -439,18 +356,10 @@ static int hisi_ddrc_pmu_dev_probe(struct platform_de= vice *pdev, if (ret) return ret; =20 - if (ddrc_pmu->identifier >=3D HISI_PMU_V2) { - ddrc_pmu->counter_bits =3D 48; - ddrc_pmu->check_event =3D DDRC_V2_NR_EVENTS; - ddrc_pmu->pmu_events.attr_groups =3D hisi_ddrc_pmu_v2_attr_groups; - ddrc_pmu->ops =3D &hisi_uncore_ddrc_v2_ops; - } else { - ddrc_pmu->counter_bits =3D 32; - ddrc_pmu->check_event =3D DDRC_V1_NR_EVENTS; - ddrc_pmu->pmu_events.attr_groups =3D hisi_ddrc_pmu_v1_attr_groups; - ddrc_pmu->ops =3D &hisi_uncore_ddrc_v1_ops; - } - + ddrc_pmu->pmu_events.attr_groups =3D ddrc_pmu->dev_info->attr_groups; + ddrc_pmu->counter_bits =3D ddrc_pmu->dev_info->counter_bits; + ddrc_pmu->check_event =3D ddrc_pmu->dev_info->check_event; + ddrc_pmu->ops =3D &hisi_uncore_ddrc_ops; ddrc_pmu->num_counters =3D DDRC_NR_COUNTERS; ddrc_pmu->dev =3D &pdev->dev; ddrc_pmu->on_cpu =3D -1; @@ -515,6 +424,49 @@ static void hisi_ddrc_pmu_remove(struct platform_devic= e *pdev) &ddrc_pmu->node); } =20 +static struct hisi_ddrc_pmu_regs hisi_ddrc_v1_pmu_regs =3D { + .event_cnt =3D DDRC_UNIMPLEMENTED_REG, + .event_ctrl =3D DDRC_EVENT_CTRL, + .event_type =3D DDRC_UNIMPLEMENTED_REG, + .perf_ctrl =3D DDRC_PERF_CTRL, + .perf_ctrl_en =3D DDRC_V1_PERF_CTRL_EN, + .int_mask =3D DDRC_INT_MASK, + .int_clear =3D DDRC_INT_CLEAR, + .int_status =3D DDRC_INT_STATUS, +}; + +static const struct hisi_pmu_dev_info hisi_ddrc_v1 =3D { + .counter_bits =3D 32, + .check_event =3D DDRC_V1_NR_EVENTS, + .attr_groups =3D hisi_ddrc_pmu_v1_attr_groups, + .private =3D &hisi_ddrc_v1_pmu_regs, +}; + +static struct hisi_ddrc_pmu_regs hisi_ddrc_v2_pmu_regs =3D { + .event_cnt =3D DDRC_V2_EVENT_CNT, + .event_ctrl =3D DDRC_V2_EVENT_CTRL, + .event_type =3D DDRC_V2_EVENT_TYPE, + .perf_ctrl =3D DDRC_V2_PERF_CTRL, + .perf_ctrl_en =3D DDRC_V2_PERF_CTRL_EN, + .int_mask =3D DDRC_V2_INT_MASK, + .int_clear =3D DDRC_V2_INT_CLEAR, + .int_status =3D DDRC_V2_INT_STATUS, +}; + +static const struct hisi_pmu_dev_info hisi_ddrc_v2 =3D { + .counter_bits =3D 48, + .check_event =3D DDRC_V2_NR_EVENTS, + .attr_groups =3D hisi_ddrc_pmu_v2_attr_groups, + .private =3D &hisi_ddrc_v2_pmu_regs, +}; + +static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] =3D { + { "HISI0233", (kernel_ulong_t)&hisi_ddrc_v1 }, + { "HISI0234", (kernel_ulong_t)&hisi_ddrc_v2 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match); + static struct platform_driver hisi_ddrc_pmu_driver =3D { .driver =3D { .name =3D "hisi_ddrc_pmu", diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisili= con/hisi_uncore_pmu.h index f4fed2544877..777675838b80 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h @@ -72,6 +72,8 @@ struct hisi_uncore_ops { struct hisi_pmu_dev_info { const char *name; const struct attribute_group **attr_groups; + u32 counter_bits; + u32 check_event; void *private; }; =20 --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga06-in.huawei.com (szxga06-in.huawei.com [45.249.212.32]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A262124DFF3 for ; Thu, 19 Jun 2025 12:56:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.32 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337775; cv=none; b=n0EI4ApGx74B4B8/rbiA5+T+vTKMVClHMoGC2JdyJW/pzhq0MF88Ooy6rhZ+mAOx7s0HIUcQqJ7gBLVlpzpdn7Oxp2F1x7SrgOt/xLH9uw5LFccVQoKE9k/3MIdIe3BLdTgqwroVN7cQcBdVdzJBshulm8TRNs8h6VVVZxiyEcI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337775; c=relaxed/simple; bh=uoLgiES/dfx8er3hrl4HglCoF+f3qY2anNwqB7c8KoA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=FK3mLc8gjc1/utvn3w/fapbwR0kvjJZLf5hFAvuPl2WLQWIxlrIeW+uqmifw4uQ3dVeCUjRYcF190xu+a1IR/P6IWgMG+zRtUIumd5Mt1k+m6LEdhl5lFWVadLSA93FrteWspG513LODyoqkOGsTwDFvDrz/l1D8Z843Ahs80J0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.32 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4bNLGg1Dmyz2QTws; Thu, 19 Jun 2025 20:56:59 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id 1DA451A0188; Thu, 19 Jun 2025 20:56:05 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:04 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:04 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 2/8] drivers/perf: hisi: Add support for HiSilicon DDRC v3 PMU driver Date: Thu, 19 Jun 2025 20:55:51 +0800 Message-ID: <20250619125557.57372-3-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He HiSilicon DDRC v3 PMU has the different interrupt register offset compared to the v2. Add device information of v3 PMU with ACPI HID HISI0235. Signed-off-by: Junhao He Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_ddrc_pmu.c index 7e3c2436e96b..26eaa6d20c00 100644 --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c @@ -43,6 +43,11 @@ #define DDRC_V2_EVENT_TYPE 0xe74 #define DDRC_V2_PERF_CTRL 0xeA0 =20 +/* DDRC interrupt registers definition in v3 */ +#define DDRC_V3_INT_MASK 0x534 +#define DDRC_V3_INT_STATUS 0x538 +#define DDRC_V3_INT_CLEAR 0x53C + /* DDRC has 8-counters */ #define DDRC_NR_COUNTERS 0x8 #define DDRC_V1_PERF_CTRL_EN 0x2 @@ -460,9 +465,28 @@ static const struct hisi_pmu_dev_info hisi_ddrc_v2 =3D= { .private =3D &hisi_ddrc_v2_pmu_regs, }; =20 +static struct hisi_ddrc_pmu_regs hisi_ddrc_v3_pmu_regs =3D { + .event_cnt =3D DDRC_V2_EVENT_CNT, + .event_ctrl =3D DDRC_V2_EVENT_CTRL, + .event_type =3D DDRC_V2_EVENT_TYPE, + .perf_ctrl =3D DDRC_V2_PERF_CTRL, + .perf_ctrl_en =3D DDRC_V2_PERF_CTRL_EN, + .int_mask =3D DDRC_V3_INT_MASK, + .int_clear =3D DDRC_V3_INT_CLEAR, + .int_status =3D DDRC_V3_INT_STATUS, +}; + +static const struct hisi_pmu_dev_info hisi_ddrc_v3 =3D { + .counter_bits =3D 48, + .check_event =3D DDRC_V2_NR_EVENTS, + .attr_groups =3D hisi_ddrc_pmu_v2_attr_groups, + .private =3D &hisi_ddrc_v3_pmu_regs, +}; + static const struct acpi_device_id hisi_ddrc_pmu_acpi_match[] =3D { { "HISI0233", (kernel_ulong_t)&hisi_ddrc_v1 }, { "HISI0234", (kernel_ulong_t)&hisi_ddrc_v2 }, + { "HISI0235", (kernel_ulong_t)&hisi_ddrc_v3 }, {} }; MODULE_DEVICE_TABLE(acpi, hisi_ddrc_pmu_acpi_match); --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4BBCE2417F2 for ; Thu, 19 Jun 2025 12:56:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.190 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337771; cv=none; b=DXVrLkN3/6oqiLJ8Sn+WxJcaUDhrxzcZ4WlzuzoUEj968gNqwWZ7Gb2ezh1Mc4LNxnFL2AJoh3O8RLpWQIggOe35SNRDDuiMNRFxTHbgpIztuR6VYcIppHeJL9lSz8oqE/4xf7DVLi9NZDt0RcgUqQe9NwCXtLnmeyp05CoHEss= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337771; c=relaxed/simple; bh=n9Zjkea1/hAIe2WMs4AZZP5u24xKYRiquJ8wdVUn1h0=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jWrnhZ9pIxYJM49hgese7Uxu1E7dQ61qMxmzn79i3qznvg1Yr2uLJTePT1v30AW2kCIA9k+oM36lFXFfjb4QEFdA2la7GJeETK6C42OBnUMjUcPRXmVBOoIcIEXJu7sy+bP6hdlv06WfCbrpFobzeTsm+VsdsCrvMnqAYGoIyRI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.190 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4bNL965hQQz2CffQ; Thu, 19 Jun 2025 20:52:10 +0800 (CST) Received: from dggemv705-chm.china.huawei.com (unknown [10.3.19.32]) by mail.maildlp.com (Postfix) with ESMTPS id B1107140123; Thu, 19 Jun 2025 20:56:05 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv705-chm.china.huawei.com (10.3.19.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:05 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:04 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 3/8] drivers/perf: hisi: Use ACPI driver_data to retrieve SLLC PMU information Date: Thu, 19 Jun 2025 20:55:52 +0800 Message-ID: <20250619125557.57372-4-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He Make use of struct acpi_device_id::driver_data for version specific information rather than judge the version register. This will help to simplify the probe process and also a bit easier for extension. Factor out SLLC register definition to struct hisi_sllc_pmu_regs. No functional changes intended. Reviewed-by: Jonathan Cameron Signed-off-by: Junhao He Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 178 ++++++++++++------ 1 file changed, 118 insertions(+), 60 deletions(-) diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_sllc_pmu.c index dbd079016fc4..79327639ec17 100644 --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c @@ -41,6 +41,7 @@ #define SLLC_SRCID_CMD_SHIFT 1 #define SLLC_SRCID_MSK_SHIFT 12 #define SLLC_NR_EVENTS 0x80 +#define SLLC_EVENT_CNTn(cnt0, n) ((cnt0) + (n) * 8) =20 HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0); HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_max, config1, 21, 11); @@ -48,6 +49,23 @@ HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 32, 22= ); HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 43, 33); HISI_PMU_EVENT_ATTR_EXTRACTOR(tracetag_en, config1, 44, 44); =20 +struct hisi_sllc_pmu_regs { + u32 int_mask; + u32 int_clear; + u32 int_status; + u32 perf_ctrl; + u32 srcid_ctrl; + u32 srcid_cmd_shift; + u32 srcid_mask_shift; + u32 tgtid_ctrl; + u32 tgtid_min_shift; + u32 tgtid_max_shift; + u32 event_ctrl; + u32 event_type0; + u32 version; + u32 event_cnt0; +}; + static bool tgtid_is_valid(u32 max, u32 min) { return max > 0 && max >=3D min; @@ -56,96 +74,104 @@ static bool tgtid_is_valid(u32 max, u32 min) static void hisi_sllc_pmu_enable_tracetag(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 tt_en =3D hisi_get_tracetag_en(event); =20 if (tt_en) { u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val |=3D SLLC_TRACETAG_EN | SLLC_FILT_EN; - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 static void hisi_sllc_pmu_disable_tracetag(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 tt_en =3D hisi_get_tracetag_en(event); =20 if (tt_en) { u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val &=3D ~(SLLC_TRACETAG_EN | SLLC_FILT_EN); - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 static void hisi_sllc_pmu_config_tgtid(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 min =3D hisi_get_tgtid_min(event); u32 max =3D hisi_get_tgtid_max(event); =20 if (tgtid_is_valid(max, min)) { - u32 val =3D (max << SLLC_TGTID_MAX_SHIFT) | (min << SLLC_TGTID_MIN_SHIFT= ); + u32 val =3D (max << regs->tgtid_max_shift) | + (min << regs->tgtid_min_shift); =20 - writel(val, sllc_pmu->base + SLLC_TGTID_CTRL); + writel(val, sllc_pmu->base + regs->tgtid_ctrl); /* Enable the tgtid */ - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val |=3D SLLC_TGTID_EN | SLLC_FILT_EN; - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 static void hisi_sllc_pmu_clear_tgtid(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 min =3D hisi_get_tgtid_min(event); u32 max =3D hisi_get_tgtid_max(event); =20 if (tgtid_is_valid(max, min)) { u32 val; =20 - writel(SLLC_TGTID_NONE, sllc_pmu->base + SLLC_TGTID_CTRL); + writel(SLLC_TGTID_NONE, sllc_pmu->base + regs->tgtid_ctrl); /* Disable the tgtid */ - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val &=3D ~(SLLC_TGTID_EN | SLLC_FILT_EN); - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 static void hisi_sllc_pmu_config_srcid(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 cmd =3D hisi_get_srcid_cmd(event); =20 if (cmd) { u32 val, msk; =20 msk =3D hisi_get_srcid_msk(event); - val =3D (cmd << SLLC_SRCID_CMD_SHIFT) | (msk << SLLC_SRCID_MSK_SHIFT); - writel(val, sllc_pmu->base + SLLC_SRCID_CTRL); + val =3D (cmd << regs->srcid_cmd_shift) | + (msk << regs->srcid_mask_shift); + writel(val, sllc_pmu->base + regs->srcid_ctrl); /* Enable the srcid */ - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val |=3D SLLC_SRCID_EN | SLLC_FILT_EN; - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 static void hisi_sllc_pmu_clear_srcid(struct perf_event *event) { struct hisi_pmu *sllc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 cmd =3D hisi_get_srcid_cmd(event); =20 if (cmd) { u32 val; =20 - writel(SLLC_SRCID_NONE, sllc_pmu->base + SLLC_SRCID_CTRL); + writel(SLLC_SRCID_NONE, sllc_pmu->base + regs->srcid_ctrl); /* Disable the srcid */ - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val &=3D ~(SLLC_SRCID_EN | SLLC_FILT_EN); - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } } =20 @@ -167,29 +193,27 @@ static void hisi_sllc_pmu_clear_filter(struct perf_ev= ent *event) } } =20 -static u32 hisi_sllc_pmu_get_counter_offset(int idx) -{ - return (SLLC_EVENT_CNT0_L + idx * 8); -} - static u64 hisi_sllc_pmu_read_counter(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc) { - return readq(sllc_pmu->base + - hisi_sllc_pmu_get_counter_offset(hwc->idx)); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; + + return readq(sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx)= ); } =20 static void hisi_sllc_pmu_write_counter(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc, u64 val) { - writeq(val, sllc_pmu->base + - hisi_sllc_pmu_get_counter_offset(hwc->idx)); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; + + writeq(val, sllc_pmu->base + SLLC_EVENT_CNTn(regs->event_cnt0, hwc->idx)); } =20 static void hisi_sllc_pmu_write_evtype(struct hisi_pmu *sllc_pmu, int idx, u32 type) { - u32 reg, reg_idx, shift, val; + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; + u32 reg, val; =20 /* * Select the appropriate event select register(SLLC_EVENT_TYPE0/1). @@ -198,96 +222,98 @@ static void hisi_sllc_pmu_write_evtype(struct hisi_pm= u *sllc_pmu, int idx, * SLLC_EVENT_TYPE0 is chosen. For the latter 4 hardware counters, * SLLC_EVENT_TYPE1 is chosen. */ - reg =3D SLLC_EVENT_TYPE0 + (idx / 4) * 4; - reg_idx =3D idx % 4; - shift =3D 8 * reg_idx; + reg =3D regs->event_type0 + (idx / 4) * 4; =20 /* Write event code to SLLC_EVENT_TYPEx Register */ val =3D readl(sllc_pmu->base + reg); - val &=3D ~(SLLC_EVTYPE_MASK << shift); - val |=3D (type << shift); + val &=3D ~(SLLC_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx)); + val |=3D (type << HISI_PMU_EVTYPE_SHIFT(idx)); writel(val, sllc_pmu->base + reg); } =20 static void hisi_sllc_pmu_start_counters(struct hisi_pmu *sllc_pmu) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val |=3D SLLC_PERF_CTRL_EN; - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } =20 static void hisi_sllc_pmu_stop_counters(struct hisi_pmu *sllc_pmu) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_PERF_CTRL); + val =3D readl(sllc_pmu->base + regs->perf_ctrl); val &=3D ~(SLLC_PERF_CTRL_EN); - writel(val, sllc_pmu->base + SLLC_PERF_CTRL); + writel(val, sllc_pmu->base + regs->perf_ctrl); } =20 static void hisi_sllc_pmu_enable_counter(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_EVENT_CTRL); - val |=3D 1 << hwc->idx; - writel(val, sllc_pmu->base + SLLC_EVENT_CTRL); + val =3D readl(sllc_pmu->base + regs->event_ctrl); + val |=3D BIT_ULL(hwc->idx); + writel(val, sllc_pmu->base + regs->event_ctrl); } =20 static void hisi_sllc_pmu_disable_counter(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_EVENT_CTRL); - val &=3D ~(1 << hwc->idx); - writel(val, sllc_pmu->base + SLLC_EVENT_CTRL); + val =3D readl(sllc_pmu->base + regs->event_ctrl); + val &=3D ~BIT_ULL(hwc->idx); + writel(val, sllc_pmu->base + regs->event_ctrl); } =20 static void hisi_sllc_pmu_enable_counter_int(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_INT_MASK); - /* Write 0 to enable interrupt */ - val &=3D ~(1 << hwc->idx); - writel(val, sllc_pmu->base + SLLC_INT_MASK); + val =3D readl(sllc_pmu->base + regs->int_mask); + val &=3D ~BIT_ULL(hwc->idx); + writel(val, sllc_pmu->base + regs->int_mask); } =20 static void hisi_sllc_pmu_disable_counter_int(struct hisi_pmu *sllc_pmu, struct hw_perf_event *hwc) { + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; u32 val; =20 - val =3D readl(sllc_pmu->base + SLLC_INT_MASK); - /* Write 1 to mask interrupt */ - val |=3D 1 << hwc->idx; - writel(val, sllc_pmu->base + SLLC_INT_MASK); + val =3D readl(sllc_pmu->base + regs->int_mask); + val |=3D BIT_ULL(hwc->idx); + writel(val, sllc_pmu->base + regs->int_mask); } =20 static u32 hisi_sllc_pmu_get_int_status(struct hisi_pmu *sllc_pmu) { - return readl(sllc_pmu->base + SLLC_INT_STATUS); + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; + + return readl(sllc_pmu->base + regs->int_status); } =20 static void hisi_sllc_pmu_clear_int_status(struct hisi_pmu *sllc_pmu, int = idx) { - writel(1 << idx, sllc_pmu->base + SLLC_INT_CLEAR); -} + struct hisi_sllc_pmu_regs *regs =3D sllc_pmu->dev_info->private; =20 -static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] =3D { - { "HISI0263", }, - {} -}; -MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match); + writel(BIT_ULL(idx), sllc_pmu->base + regs->int_clear); +} =20 static int hisi_sllc_pmu_init_data(struct platform_device *pdev, struct hisi_pmu *sllc_pmu) { + struct hisi_sllc_pmu_regs *regs; + hisi_uncore_pmu_init_topology(sllc_pmu, &pdev->dev); =20 /* @@ -304,13 +330,18 @@ static int hisi_sllc_pmu_init_data(struct platform_de= vice *pdev, return -EINVAL; } =20 + sllc_pmu->dev_info =3D device_get_match_data(&pdev->dev); + if (!sllc_pmu->dev_info) + return -ENODEV; + sllc_pmu->base =3D devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(sllc_pmu->base)) { dev_err(&pdev->dev, "ioremap failed for sllc_pmu resource.\n"); return PTR_ERR(sllc_pmu->base); } =20 - sllc_pmu->identifier =3D readl(sllc_pmu->base + SLLC_VERSION); + regs =3D sllc_pmu->dev_info->private; + sllc_pmu->identifier =3D readl(sllc_pmu->base + regs->version); =20 return 0; } @@ -352,6 +383,27 @@ static const struct attribute_group *hisi_sllc_pmu_v2_= attr_groups[] =3D { NULL }; =20 +static struct hisi_sllc_pmu_regs hisi_sllc_v2_pmu_regs =3D { + .int_mask =3D SLLC_INT_MASK, + .int_clear =3D SLLC_INT_CLEAR, + .int_status =3D SLLC_INT_STATUS, + .perf_ctrl =3D SLLC_PERF_CTRL, + .srcid_ctrl =3D SLLC_SRCID_CTRL, + .srcid_cmd_shift =3D SLLC_SRCID_CMD_SHIFT, + .srcid_mask_shift =3D SLLC_SRCID_MSK_SHIFT, + .tgtid_ctrl =3D SLLC_TGTID_CTRL, + .tgtid_min_shift =3D SLLC_TGTID_MIN_SHIFT, + .tgtid_max_shift =3D SLLC_TGTID_MAX_SHIFT, + .event_ctrl =3D SLLC_EVENT_CTRL, + .event_type0 =3D SLLC_EVENT_TYPE0, + .version =3D SLLC_VERSION, + .event_cnt0 =3D SLLC_EVENT_CNT0_L, +}; + +static const struct hisi_pmu_dev_info hisi_sllc_v2 =3D { + .private =3D &hisi_sllc_v2_pmu_regs, +}; + static const struct hisi_uncore_ops hisi_uncore_sllc_ops =3D { .write_evtype =3D hisi_sllc_pmu_write_evtype, .get_event_idx =3D hisi_uncore_pmu_get_event_idx, @@ -443,6 +495,12 @@ static void hisi_sllc_pmu_remove(struct platform_devic= e *pdev) &sllc_pmu->node); } =20 +static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] =3D { + { "HISI0263", (kernel_ulong_t)&hisi_sllc_v2 }, + {} +}; +MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match); + static struct platform_driver hisi_sllc_pmu_driver =3D { .driver =3D { .name =3D "hisi_sllc_pmu", --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 847B324EF8B for ; Thu, 19 Jun 2025 12:56:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; cv=none; b=ENFxwnfRss05kD5OP82SNaH5Xn3KQ6oBXVvdSxqUIRvTn6e03Fk+tx67RmAlTYLpMOIxtCzpAUdrlwVhahhc0WR/fkTAG7nL6eKoCp6PwkxyVv2Q4oczkRxDmEUe55KicTMInHTPJm8gNQvvr0aJtE0hmEMDT8nkGodOfwF2nyo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; c=relaxed/simple; bh=dyRpH0nYuNks3GpNno7ihwa0O5nmvtWOu7ZWSkNXlcg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=MSoaeq3FBhioQbM4B18qOf2RkTSDmUZ8ryrjjALyN7nlryANiH5hEj3Ty5cB2o2WiWekOQIKxbAMI7sqUQB3hTnNjNdt9f8xBduULnD/Ba89Fm17B5Xi/2h2UHK1wQExrdoGX6R0fvaP8v/qfq68hEEc4/3ujh3ZiCEP+QmKWDo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.88.194]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4bNL8j2VYLzRk4n; Thu, 19 Jun 2025 20:51:49 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 3D21B1400D9; Thu, 19 Jun 2025 20:56:06 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:06 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:05 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 4/8] drivers/perf: hisi: Add support for HiSilicon SLLC v3 PMU driver Date: Thu, 19 Jun 2025 20:55:53 +0800 Message-ID: <20250619125557.57372-5-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He SLLC v3 PMU has the following changes compared to previous version: a) update the register layout b) update the definition of SRCID_CTRL and TGTID_CTRL registers. To be compatible with v2, we use maximum width (11 bits) and mask the extra length for themselves. c) remove latency events (driver does not need to be adapted). SLLC v3 PMU is identified with HID HISI0264. Signed-off-by: Junhao He Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_sllc_pmu.c index 79327639ec17..852114cfe3bf 100644 --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c @@ -28,6 +28,18 @@ #define SLLC_VERSION 0x1cf0 #define SLLC_EVENT_CNT0_L 0x1d00 =20 +/* SLLC registers definition in v3 */ +#define SLLC_V3_INT_MASK 0x6834 +#define SLLC_V3_INT_STATUS 0x6838 +#define SLLC_V3_INT_CLEAR 0x683c +#define SLLC_V3_VERSION 0x6c00 +#define SLLC_V3_PERF_CTRL 0x6d00 +#define SLLC_V3_SRCID_CTRL 0x6d04 +#define SLLC_V3_TGTID_CTRL 0x6d08 +#define SLLC_V3_EVENT_CTRL 0x6d14 +#define SLLC_V3_EVENT_TYPE0 0x6d18 +#define SLLC_V3_EVENT_CNT0_L 0x6e00 + #define SLLC_EVTYPE_MASK 0xff #define SLLC_PERF_CTRL_EN BIT(0) #define SLLC_FILT_EN BIT(1) @@ -40,6 +52,12 @@ #define SLLC_TGTID_MAX_SHIFT 12 #define SLLC_SRCID_CMD_SHIFT 1 #define SLLC_SRCID_MSK_SHIFT 12 + +#define SLLC_V3_TGTID_MIN_SHIFT 1 +#define SLLC_V3_TGTID_MAX_SHIFT 10 +#define SLLC_V3_SRCID_CMD_SHIFT 1 +#define SLLC_V3_SRCID_MSK_SHIFT 10 + #define SLLC_NR_EVENTS 0x80 #define SLLC_EVENT_CNTn(cnt0, n) ((cnt0) + (n) * 8) =20 @@ -404,6 +422,27 @@ static const struct hisi_pmu_dev_info hisi_sllc_v2 =3D= { .private =3D &hisi_sllc_v2_pmu_regs, }; =20 +static struct hisi_sllc_pmu_regs hisi_sllc_v3_pmu_regs =3D { + .int_mask =3D SLLC_V3_INT_MASK, + .int_clear =3D SLLC_V3_INT_CLEAR, + .int_status =3D SLLC_V3_INT_STATUS, + .perf_ctrl =3D SLLC_V3_PERF_CTRL, + .srcid_ctrl =3D SLLC_V3_SRCID_CTRL, + .srcid_cmd_shift =3D SLLC_V3_SRCID_CMD_SHIFT, + .srcid_mask_shift =3D SLLC_V3_SRCID_MSK_SHIFT, + .tgtid_ctrl =3D SLLC_V3_TGTID_CTRL, + .tgtid_min_shift =3D SLLC_V3_TGTID_MIN_SHIFT, + .tgtid_max_shift =3D SLLC_V3_TGTID_MAX_SHIFT, + .event_ctrl =3D SLLC_V3_EVENT_CTRL, + .event_type0 =3D SLLC_V3_EVENT_TYPE0, + .version =3D SLLC_V3_VERSION, + .event_cnt0 =3D SLLC_V3_EVENT_CNT0_L, +}; + +static const struct hisi_pmu_dev_info hisi_sllc_v3 =3D { + .private =3D &hisi_sllc_v3_pmu_regs, +}; + static const struct hisi_uncore_ops hisi_uncore_sllc_ops =3D { .write_evtype =3D hisi_sllc_pmu_write_evtype, .get_event_idx =3D hisi_uncore_pmu_get_event_idx, @@ -497,6 +536,7 @@ static void hisi_sllc_pmu_remove(struct platform_device= *pdev) =20 static const struct acpi_device_id hisi_sllc_pmu_acpi_match[] =3D { { "HISI0263", (kernel_ulong_t)&hisi_sllc_v2 }, + { "HISI0264", (kernel_ulong_t)&hisi_sllc_v3 }, {} }; MODULE_DEVICE_TABLE(acpi, hisi_sllc_pmu_acpi_match); --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4852A242927 for ; Thu, 19 Jun 2025 12:56:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337772; cv=none; b=dC/90cKV4nzjrB/kwNO3uBu20WSq2pa1wnnQz/dPUFIGxY73PuDrfv0zdzxfASxRGvxK8NldBQk9ZQK73Rc3QbU0jcVqu+w74X05SXxz8SqV1pEWxJ2gFzShoNxEwsc2i5RKeqb5qPD4ejND/oy+8AwBw7h2d3yBrvyuMUJdqJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337772; c=relaxed/simple; bh=YJ5hacusdQyGhXv53oxsZxWFAuPyPsvP8kKGHnbYb7Y=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NsY4YqVu1CgPd/s3ZEwWE2PiMcqsiqhspsmVZEFUaeXRQPhwQt4mglhGGUieXCeSxuKm3AicjJdG7c98s8nPnubtecmjJOxRH4JbfAHjMEl4r2ccuv+M/sEB9ZS1a8RVvp7IrKanhaJW33kd1aMRu2auglmHlK+ZhtovLF1j3iI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.17]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4bNLCx0tv4z2BdgT; Thu, 19 Jun 2025 20:54:37 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 6F1841A0188; Thu, 19 Jun 2025 20:56:06 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:06 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:05 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 5/8] drivers/perf: hisi: Relax the event number check of v2 PMUs Date: Thu, 19 Jun 2025 20:55:54 +0800 Message-ID: <20250619125557.57372-6-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He The supported event number range of each Uncore PMUs is provided by each driver in hisi_pmu::check_event and out of range events will be rejected. A later version with expanded event number range needs to register the PMU with updated hisi_pmu::check_event even if it's the only update, which means the expanded events cannot be used unless the driver's updated. However the unsupported events won't be counted by the hardware so we can relax the event number check to allow the use the expanded events. Reviewed-by: Jonathan Cameron Signed-off-by: Junhao He Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c | 2 +- drivers/perf/hisilicon/hisi_uncore_hha_pmu.c | 6 +++--- drivers/perf/hisilicon/hisi_uncore_pa_pmu.c | 2 +- drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_ddrc_pmu.c index 26eaa6d20c00..21c494881ca0 100644 --- a/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_ddrc_pmu.c @@ -53,7 +53,7 @@ #define DDRC_V1_PERF_CTRL_EN 0x2 #define DDRC_V2_PERF_CTRL_EN 0x1 #define DDRC_V1_NR_EVENTS 0x7 -#define DDRC_V2_NR_EVENTS 0x90 +#define DDRC_V2_NR_EVENTS 0xFF =20 #define DDRC_EVENT_CNTn(base, n) ((base) + (n) * 8) #define DDRC_EVENT_TYPEn(base, n) ((base) + (n) * 4) diff --git a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c b/drivers/perf/hi= silicon/hisi_uncore_hha_pmu.c index ca609db86046..97cfaa586a87 100644 --- a/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_hha_pmu.c @@ -47,9 +47,9 @@ #define HHA_SRCID_CMD GENMASK(16, 6) #define HHA_SRCID_MSK GENMASK(30, 20) #define HHA_DATSRC_SKT_EN BIT(23) -#define HHA_EVTYPE_NONE 0xff +#define HHA_EVTYPE_MASK GENMASK(7, 0) #define HHA_V1_NR_EVENT 0x65 -#define HHA_V2_NR_EVENT 0xCE +#define HHA_V2_NR_EVENT 0xFF =20 HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_cmd, config1, 10, 0); HISI_PMU_EVENT_ATTR_EXTRACTOR(srcid_msk, config1, 21, 11); @@ -197,7 +197,7 @@ static void hisi_hha_pmu_write_evtype(struct hisi_pmu *= hha_pmu, int idx, =20 /* Write event code to HHA_EVENT_TYPEx register */ val =3D readl(hha_pmu->base + reg); - val &=3D ~(HHA_EVTYPE_NONE << shift); + val &=3D ~(HHA_EVTYPE_MASK << shift); val |=3D (type << shift); writel(val, hha_pmu->base + reg); } diff --git a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c b/drivers/perf/his= ilicon/hisi_uncore_pa_pmu.c index a0142684e379..80108c63cb60 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pa_pmu.c @@ -440,7 +440,7 @@ static int hisi_pa_pmu_dev_probe(struct platform_device= *pdev, pa_pmu->pmu_events.attr_groups =3D pa_pmu->dev_info->attr_groups; pa_pmu->num_counters =3D PA_NR_COUNTERS; pa_pmu->ops =3D &hisi_uncore_pa_ops; - pa_pmu->check_event =3D 0xB0; + pa_pmu->check_event =3D PA_EVTYPE_MASK; pa_pmu->counter_bits =3D 64; pa_pmu->dev =3D &pdev->dev; pa_pmu->on_cpu =3D -1; diff --git a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c b/drivers/perf/h= isilicon/hisi_uncore_sllc_pmu.c index 852114cfe3bf..cd32d606df05 100644 --- a/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_sllc_pmu.c @@ -58,7 +58,7 @@ #define SLLC_V3_SRCID_CMD_SHIFT 1 #define SLLC_V3_SRCID_MSK_SHIFT 10 =20 -#define SLLC_NR_EVENTS 0x80 +#define SLLC_NR_EVENTS 0xff #define SLLC_EVENT_CNTn(cnt0, n) ((cnt0) + (n) * 8) =20 HISI_PMU_EVENT_ATTR_EXTRACTOR(tgtid_min, config1, 10, 0); --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C34C5242927 for ; Thu, 19 Jun 2025 12:56:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; cv=none; b=tQFvFkmUc+oMUhuFYSaM7wuXHbxDS8AvkEB0lZE5k3XPHwbevQ2mR06vWgihO3xqFUHcITAdtMhDD60qeqHwnX8p5pq1KoT4B+NW1KNCW1truq1/2Ez/4D3qG/wZV7qp/OgroeCgcUZHgqD+sfMZn6/dHud/2RTZoS4N7FNEbJU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337776; c=relaxed/simple; bh=UWGhNmEgg6U58d6ixt8pbV8lVM2E/k1Ms9AvRHA/JsA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=WkM70FkxG8tD0yms181f45D3pjHWZUoZ/apZBYVhpAVTqNatSK3gA6m/Ojnl2lyU2zXSZFx6Y8Gp6zQjC27qpGgsxeov4mkibRhDNjnZlm1BtzuIB9h7aB5gH03T72jZtGeAr8fl9PK+qlVamGzGiw4E6zfTyASNRAEW7eGSzu0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.174]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4bNL8k1jtvzRk68; Thu, 19 Jun 2025 20:51:50 +0800 (CST) Received: from dggemv712-chm.china.huawei.com (unknown [10.1.198.32]) by mail.maildlp.com (Postfix) with ESMTPS id 2346414011A; Thu, 19 Jun 2025 20:56:07 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv712-chm.china.huawei.com (10.1.198.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:06 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:06 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 6/8] drivers/perf: hisi: Support PMUs with no interrupt Date: Thu, 19 Jun 2025 20:55:55 +0800 Message-ID: <20250619125557.57372-7-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Yicong Yang We'll have PMUs don't have an interrupt to indicate the counter overflow, but the Uncore PMU core assume all the PMUs have interrupt. So handle this case in the core. The existing PMUs won't be affected. Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/hisi_uncore_pmu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.c b/drivers/perf/hisili= con/hisi_uncore_pmu.c index ef058b1dd509..a449651f79c9 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.c +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.c @@ -510,7 +510,9 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct= hlist_node *node) return 0; =20 hisi_pmu->on_cpu =3D cpumask_local_spread(0, dev_to_node(hisi_pmu->dev)); - WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(hisi_pmu->on_cpu))); + if (hisi_pmu->irq > 0) + WARN_ON(irq_set_affinity(hisi_pmu->irq, + cpumask_of(hisi_pmu->on_cpu))); return 0; } =20 @@ -525,7 +527,8 @@ int hisi_uncore_pmu_online_cpu(unsigned int cpu, struct= hlist_node *node) hisi_pmu->on_cpu =3D cpu; =20 /* Overflow interrupt also should use the same CPU */ - WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu))); + if (hisi_pmu->irq > 0) + WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(cpu))); =20 return 0; } @@ -560,7 +563,9 @@ int hisi_uncore_pmu_offline_cpu(unsigned int cpu, struc= t hlist_node *node) perf_pmu_migrate_context(&hisi_pmu->pmu, cpu, target); /* Use this CPU for event counting */ hisi_pmu->on_cpu =3D target; - WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target))); + + if (hisi_pmu->irq > 0) + WARN_ON(irq_set_affinity(hisi_pmu->irq, cpumask_of(target))); =20 return 0; } --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E16AC2472A6 for ; Thu, 19 Jun 2025 12:56:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.255 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337793; cv=none; b=TN73dchwKRTmafUineD+96Xh5+tZr8dC3RMtJI/duwZJ4fozxJfpLrwJ+KQ1tcyenUebQ0mgPr3ExjOjqsr8c0sUV4vFXnQbuzeHX1TMEIgDT1eJkCMiGrdACYQhgDUmtd675VDuLdb+sh70veV0/C5Jr5K52OkhhuP/BQ7k+bQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337793; c=relaxed/simple; bh=p6/Y0d9dwhDGKZWB06xHh8+iQQk91NnAjJKzZuqVnDc=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=P9pp8KzTLE6RecDUHxd9puSuEjytMyd3R2cctEBzkQpPLojmJ+pTkwGbd92zJPqPa0P0v2tncwH0titp0x5CxPWSLIaEE95KbF+c5SoriEW5ZfeVPinFS+CAPkym20JVl6dWzm/SPI8YKDhU1nsqWtS/5EhTnmnCgeIhkINTBhQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.255 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.252]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4bNLCP55CPz1d1p2; Thu, 19 Jun 2025 20:54:09 +0800 (CST) Received: from dggemv705-chm.china.huawei.com (unknown [10.3.19.32]) by mail.maildlp.com (Postfix) with ESMTPS id A0930180B72; Thu, 19 Jun 2025 20:56:22 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv705-chm.china.huawei.com (10.3.19.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:07 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:06 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 7/8] drivers/perf: hisi: Add support for HiSilicon NoC PMU Date: Thu, 19 Jun 2025 20:55:56 +0800 Message-ID: <20250619125557.57372-8-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Yicong Yang Adds the support for HiSilicon NoC (Network on Chip) PMU which will be used to monitor the events on the system bus. The PMU device will be named after the SCL ID (either Super CPU cluster or Super IO cluster) and the index ID, just similar to other HiSilicon Uncore PMUs. Below PMU formats are provided besides the event: - ch: the transaction channel (data, request, response, etc) which can be used to filter the counting. - tt_en: tracetag filtering enable. Just as other HiSilicon Uncore PMUs the NoC PMU supports only counting the transactions with tracetag. The NoC PMU doesn't have an interrupt to indicate the overflow. However we have a 64 bit counter which is large enough and it's nearly impossible to overflow. Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- Documentation/admin-guide/perf/hisi-pmu.rst | 11 + drivers/perf/hisilicon/Makefile | 3 +- drivers/perf/hisilicon/hisi_uncore_noc_pmu.c | 392 +++++++++++++++++++ 3 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 drivers/perf/hisilicon/hisi_uncore_noc_pmu.c diff --git a/Documentation/admin-guide/perf/hisi-pmu.rst b/Documentation/ad= min-guide/perf/hisi-pmu.rst index 48992a0b8e94..6f0ea4f641cc 100644 --- a/Documentation/admin-guide/perf/hisi-pmu.rst +++ b/Documentation/admin-guide/perf/hisi-pmu.rst @@ -112,6 +112,17 @@ uring channel. It is 2 bits. Some important codes are = as follows: - 2'b00: default value, count the events which sent to the both uring and uring_ext channel; =20 +6. ch: NoC PMU supports filtering the event counts of certain transaction +channel with this option. The current supported channels are as follows: + +- 3'b010: Request channel +- 3'b100: Snoop channel +- 3'b110: Response channel +- 3'b111: Data channel + +7. tt_en: NoC PMU supports counting only transactions that have tracetag s= et +if this option is set. See the 2nd list for more information about traceta= g. + Users could configure IDs to count data come from specific CCL/ICL, by set= ting srcid_cmd & srcid_msk, and data desitined for specific CCL/ICL by setting tgtid_cmd & tgtid_msk. A set bit in srcid_msk/tgtid_msk means the PMU will= not diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makef= ile index 48dcc8381ea7..dcec8f39719d 100644 --- a/drivers/perf/hisilicon/Makefile +++ b/drivers/perf/hisilicon/Makefile @@ -1,7 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only obj-$(CONFIG_HISI_PMU) +=3D hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ - hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o + hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o \ + hisi_uncore_noc_pmu.o =20 obj-$(CONFIG_HISI_PCIE_PMU) +=3D hisi_pcie_pmu.o obj-$(CONFIG_HNS3_PMU) +=3D hns3_pmu.o diff --git a/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c b/drivers/perf/hi= silicon/hisi_uncore_noc_pmu.c new file mode 100644 index 000000000000..1717254421f8 --- /dev/null +++ b/drivers/perf/hisilicon/hisi_uncore_noc_pmu.c @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for HiSilicon Uncore NoC (Network on Chip) PMU device + * + * Copyright (c) 2025 HiSilicon Technologies Co., Ltd. + * Author: Yicong Yang + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hisi_uncore_pmu.h" + +#define NOC_PMU_VERSION 0x1e00 +#define NOC_PMU_GLOBAL_CTRL 0x1e04 +#define NOC_PMU_GLOBAL_CTRL_PMU_EN BIT(0) +#define NOC_PMU_GLOBAL_CTRL_TT_EN BIT(1) +#define NOC_PMU_CNT_INFO 0x1e08 +#define NOC_PMU_CNT_INFO_OVERFLOW(n) BIT(n) +#define NOC_PMU_EVENT_CTRL(n) (0x1e20 + 4 * (n)) +#define NOC_PMU_EVENT_CTRL_TYPE GENMASK(4, 0) +/* + * Note channel of 0x0 will reset the counter value, so don't do it before + * we read out the counter. + */ +#define NOC_PMU_EVENT_CTRL_CHANNEL GENMASK(10, 8) +#define NOC_PMU_EVENT_CTRL_EN BIT(11) +#define NOC_PMU_EVENT_COUNTER(n) (0x1e80 + 8 * (n)) + +#define NOC_PMU_NR_COUNTERS 4 +#define NOC_PMU_COUNTER_BITS 64 + +#define NOC_PMU_CH_DEFAULT 0x7 + +HISI_PMU_EVENT_ATTR_EXTRACTOR(ch, config1, 2, 0); +HISI_PMU_EVENT_ATTR_EXTRACTOR(tt_en, config1, 3, 3); + +/* Dynamic CPU hotplug state used by this PMU driver */ +static enum cpuhp_state hisi_noc_pmu_cpuhp_state; + +/* + * Tracetag filtering is not per event and all the events should keep + * the consistence. Return true if the new comer doesn't match the + * tracetag filtering configuration of the current scheduled events. + */ +static bool hisi_noc_pmu_check_global_filter(struct perf_event *curr, + struct perf_event *new) +{ + return hisi_get_tt_en(curr) =3D=3D hisi_get_tt_en(new); +} + +static void hisi_noc_pmu_write_evtype(struct hisi_pmu *noc_pmu, int idx, u= 32 type) +{ + u32 reg; + + reg =3D readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(idx)); + reg &=3D ~NOC_PMU_EVENT_CTRL_TYPE; + reg |=3D FIELD_PREP(NOC_PMU_EVENT_CTRL_TYPE, type); + writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(idx)); +} + +static int hisi_noc_pmu_get_event_idx(struct perf_event *event) +{ + struct hisi_pmu *noc_pmu =3D to_hisi_pmu(event->pmu); + struct hisi_pmu_hwevents *pmu_events =3D &noc_pmu->pmu_events; + int cur_idx; + + cur_idx =3D find_first_bit(pmu_events->used_mask, noc_pmu->num_counters); + if (cur_idx !=3D noc_pmu->num_counters && + !hisi_noc_pmu_check_global_filter(pmu_events->hw_events[cur_idx], eve= nt)) + return -EAGAIN; + + return hisi_uncore_pmu_get_event_idx(event); +} + +static u64 hisi_noc_pmu_read_counter(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc) +{ + return readq(noc_pmu->base + NOC_PMU_EVENT_COUNTER(hwc->idx)); +} + +static void hisi_noc_pmu_write_counter(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc, u64 val) +{ + writeq(val, noc_pmu->base + NOC_PMU_EVENT_COUNTER(hwc->idx)); +} + +static void hisi_noc_pmu_enable_counter(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc) +{ + u32 reg; + + reg =3D readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); + reg |=3D NOC_PMU_EVENT_CTRL_EN; + writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); +} + +static void hisi_noc_pmu_disable_counter(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc) +{ + u32 reg; + + reg =3D readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); + reg &=3D ~NOC_PMU_EVENT_CTRL_EN; + writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); +} + +static void hisi_noc_pmu_enable_counter_int(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc) +{ + /* We don't support interrupt, so a stub here. */ +} + +static void hisi_noc_pmu_disable_counter_int(struct hisi_pmu *noc_pmu, + struct hw_perf_event *hwc) +{ +} + +static void hisi_noc_pmu_start_counters(struct hisi_pmu *noc_pmu) +{ + u32 reg; + + reg =3D readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + reg |=3D NOC_PMU_GLOBAL_CTRL_PMU_EN; + writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL); +} + +static void hisi_noc_pmu_stop_counters(struct hisi_pmu *noc_pmu) +{ + u32 reg; + + reg =3D readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + reg &=3D ~NOC_PMU_GLOBAL_CTRL_PMU_EN; + writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL); +} + +static u32 hisi_noc_pmu_get_int_status(struct hisi_pmu *noc_pmu) +{ + return readl(noc_pmu->base + NOC_PMU_CNT_INFO); +} + +static void hisi_noc_pmu_clear_int_status(struct hisi_pmu *noc_pmu, int id= x) +{ + writel(~NOC_PMU_CNT_INFO_OVERFLOW(idx), noc_pmu->base + NOC_PMU_CNT_INFO); +} + +static void hisi_noc_pmu_enable_filter(struct perf_event *event) +{ + struct hisi_pmu *noc_pmu =3D to_hisi_pmu(event->pmu); + struct hw_perf_event *hwc =3D &event->hw; + u32 tt_en =3D hisi_get_tt_en(event); + u32 ch =3D hisi_get_ch(event); + u32 reg; + + if (!ch) + ch =3D NOC_PMU_CH_DEFAULT; + + reg =3D readl(noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); + reg &=3D ~NOC_PMU_EVENT_CTRL_CHANNEL; + reg |=3D FIELD_PREP(NOC_PMU_EVENT_CTRL_CHANNEL, ch); + writel(reg, noc_pmu->base + NOC_PMU_EVENT_CTRL(hwc->idx)); + + /* + * Since tracetag filter applies to all the counters, don't touch it + * if user doesn't specify it explicitly. + */ + if (tt_en) { + reg =3D readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + reg |=3D NOC_PMU_GLOBAL_CTRL_TT_EN; + writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + } +} + +static void hisi_noc_pmu_disable_filter(struct perf_event *event) +{ + struct hisi_pmu *noc_pmu =3D to_hisi_pmu(event->pmu); + u32 tt_en =3D hisi_get_tt_en(event); + u32 reg; + + /* + * If we're not the last counter, don't touch the global tracetag + * configuration. + */ + if (bitmap_weight(noc_pmu->pmu_events.used_mask, noc_pmu->num_counters) >= 1) + return; + + if (tt_en) { + reg =3D readl(noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + reg &=3D ~NOC_PMU_GLOBAL_CTRL_TT_EN; + writel(reg, noc_pmu->base + NOC_PMU_GLOBAL_CTRL); + } +} + +static const struct hisi_uncore_ops hisi_uncore_noc_ops =3D { + .write_evtype =3D hisi_noc_pmu_write_evtype, + .get_event_idx =3D hisi_noc_pmu_get_event_idx, + .read_counter =3D hisi_noc_pmu_read_counter, + .write_counter =3D hisi_noc_pmu_write_counter, + .enable_counter =3D hisi_noc_pmu_enable_counter, + .disable_counter =3D hisi_noc_pmu_disable_counter, + .enable_counter_int =3D hisi_noc_pmu_enable_counter_int, + .disable_counter_int =3D hisi_noc_pmu_disable_counter_int, + .start_counters =3D hisi_noc_pmu_start_counters, + .stop_counters =3D hisi_noc_pmu_stop_counters, + .get_int_status =3D hisi_noc_pmu_get_int_status, + .clear_int_status =3D hisi_noc_pmu_clear_int_status, + .enable_filter =3D hisi_noc_pmu_enable_filter, + .disable_filter =3D hisi_noc_pmu_disable_filter, +}; + +static struct attribute *hisi_noc_pmu_format_attrs[] =3D { + HISI_PMU_FORMAT_ATTR(event, "config:0-7"), + HISI_PMU_FORMAT_ATTR(ch, "config1:0-2"), + HISI_PMU_FORMAT_ATTR(tt_en, "config1:3"), + NULL +}; + +static const struct attribute_group hisi_noc_pmu_format_group =3D { + .name =3D "format", + .attrs =3D hisi_noc_pmu_format_attrs, +}; + +static struct attribute *hisi_noc_pmu_events_attrs[] =3D { + HISI_PMU_EVENT_ATTR(cycles, 0x0e), + /* Flux on/off the ring */ + HISI_PMU_EVENT_ATTR(ingress_flow_sum, 0x1a), + HISI_PMU_EVENT_ATTR(egress_flow_sum, 0x17), + /* Buffer full duration on/off the ring */ + HISI_PMU_EVENT_ATTR(ingress_buf_full, 0x19), + HISI_PMU_EVENT_ATTR(egress_buf_full, 0x12), + /* Failure packets count on/off the ring */ + HISI_PMU_EVENT_ATTR(cw_ingress_fail, 0x01), + HISI_PMU_EVENT_ATTR(cc_ingress_fail, 0x09), + HISI_PMU_EVENT_ATTR(cw_egress_fail, 0x03), + HISI_PMU_EVENT_ATTR(cc_egress_fail, 0x0b), + /* Flux of the ring */ + HISI_PMU_EVENT_ATTR(cw_main_flow_sum, 0x05), + HISI_PMU_EVENT_ATTR(cc_main_flow_sum, 0x0d), + NULL +}; + +static const struct attribute_group hisi_noc_pmu_events_group =3D { + .name =3D "events", + .attrs =3D hisi_noc_pmu_events_attrs, +}; + +static const struct attribute_group *hisi_noc_pmu_attr_groups[] =3D { + &hisi_noc_pmu_format_group, + &hisi_noc_pmu_events_group, + &hisi_pmu_cpumask_attr_group, + &hisi_pmu_identifier_group, + NULL +}; + +static int hisi_noc_pmu_dev_init(struct platform_device *pdev, struct hisi= _pmu *noc_pmu) +{ + hisi_uncore_pmu_init_topology(noc_pmu, &pdev->dev); + + if (noc_pmu->topo.scl_id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, "failed to get scl-id\n"); + + if (noc_pmu->topo.index_id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, "failed to get idx-id\n"); + + if (noc_pmu->topo.sub_id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, "failed to get sub-id\n"); + + noc_pmu->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(noc_pmu->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(noc_pmu->base), + "fail to remap io memory\n"); + + noc_pmu->on_cpu =3D -1; + noc_pmu->dev =3D &pdev->dev; + noc_pmu->ops =3D &hisi_uncore_noc_ops; + noc_pmu->pmu_events.attr_groups =3D hisi_noc_pmu_attr_groups; + noc_pmu->num_counters =3D NOC_PMU_NR_COUNTERS; + noc_pmu->counter_bits =3D NOC_PMU_COUNTER_BITS; + noc_pmu->check_event =3D NOC_PMU_EVENT_CTRL_TYPE; + noc_pmu->identifier =3D readl(noc_pmu->base + NOC_PMU_VERSION); + return 0; +} + +static void hisi_noc_pmu_remove_cpuhp_instance(void *hotplug_node) +{ + cpuhp_state_remove_instance_nocalls(hisi_noc_pmu_cpuhp_state, hotplug_nod= e); +} + +static void hisi_noc_pmu_unregister_pmu(void *pmu) +{ + perf_pmu_unregister(pmu); +} + +static int hisi_noc_pmu_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct hisi_pmu *noc_pmu; + char *name; + int ret; + + noc_pmu =3D devm_kzalloc(dev, sizeof(*noc_pmu), GFP_KERNEL); + if (!noc_pmu) + return -ENOMEM; + + /* + * HiSilicon Uncore PMU framework needs to get common hisi_pmu device + * from device's drvdata. + */ + platform_set_drvdata(pdev, noc_pmu); + + ret =3D hisi_noc_pmu_dev_init(pdev, noc_pmu); + if (ret) + return ret; + + ret =3D cpuhp_state_add_instance(hisi_noc_pmu_cpuhp_state, &noc_pmu->node= ); + if (ret) + return dev_err_probe(dev, ret, "Fail to register cpuhp instance\n"); + + ret =3D devm_add_action_or_reset(dev, hisi_noc_pmu_remove_cpuhp_instance, + &noc_pmu->node); + if (ret) + return ret; + + hisi_pmu_init(noc_pmu, THIS_MODULE); + + name =3D devm_kasprintf(dev, GFP_KERNEL, "hisi_scl%d_noc%d_%d", + noc_pmu->topo.scl_id, noc_pmu->topo.index_id, + noc_pmu->topo.sub_id); + if (!name) + return -ENOMEM; + + ret =3D perf_pmu_register(&noc_pmu->pmu, name, -1); + if (ret) + return dev_err_probe(dev, ret, "Fail to register PMU\n"); + + return devm_add_action_or_reset(dev, hisi_noc_pmu_unregister_pmu, + &noc_pmu->pmu); +} + +static const struct acpi_device_id hisi_noc_pmu_ids[] =3D { + { "HISI04E0", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, hisi_noc_pmu_ids); + +static struct platform_driver hisi_noc_pmu_driver =3D { + .driver =3D { + .name =3D "hisi_noc_pmu", + .acpi_match_table =3D hisi_noc_pmu_ids, + .suppress_bind_attrs =3D true, + }, + .probe =3D hisi_noc_pmu_probe, +}; + +static int __init hisi_noc_pmu_module_init(void) +{ + int ret; + + ret =3D cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/noc:onlin= e", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); + if (ret < 0) { + pr_err("hisi_noc_pmu: Fail to setup cpuhp callbacks, ret =3D %d\n", ret); + return ret; + } + hisi_noc_pmu_cpuhp_state =3D ret; + + ret =3D platform_driver_register(&hisi_noc_pmu_driver); + if (ret) + cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state); + + return ret; +} +module_init(hisi_noc_pmu_module_init); + +static void __exit hisi_noc_pmu_module_exit(void) +{ + platform_driver_unregister(&hisi_noc_pmu_driver); + cpuhp_remove_multi_state(hisi_noc_pmu_cpuhp_state); +} +module_exit(hisi_noc_pmu_module_exit); + +MODULE_IMPORT_NS("HISI_PMU"); +MODULE_DESCRIPTION("HiSilicon SoC Uncore NoC PMU driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Yicong Yang "); --=20 2.24.0 From nobody Thu Oct 9 06:56:23 2025 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 484C9242902 for ; Thu, 19 Jun 2025 12:56:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337772; cv=none; b=sfa64lKDMGVSc9woa07o4GN+zlvxBh8AIqfK7ZyJqU35nHvn0JMdUqxThuNmMBcPnOdlRD2ds8uVYbwCEYZ/nR+fSpx5ARiNOh6q7qe9VWmcw61/SxxxbkMLnqhpKDnn8NeQ3nyTbl1N4a0/BICYOWNAH4S2OKWdDs7tSn2TFgY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1750337772; c=relaxed/simple; bh=zwED0C2xwZnEyGQrpzLm4qeCA408gSUNIeuI9Qr18Sw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AFcSTqDbMtk6sjPdhN3jLLL1zW8nlA6L5lTHdJPcBtMsZu0Gtdn0zIVBw6+NF9zNyT9LkF13LccjyJrpupLj7kDNZFZ6vEE94ihNGr8A3tDv1zD/EOFD1S5twqGDz805eqfTeBShJHFB8ZWPt9xEkTK2rbtVKx4XGqQR+/F+tKc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.163.44]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4bNLBt5XhGz28fS3; Thu, 19 Jun 2025 20:53:42 +0800 (CST) Received: from dggemv706-chm.china.huawei.com (unknown [10.3.19.33]) by mail.maildlp.com (Postfix) with ESMTPS id 0AFAF140123; Thu, 19 Jun 2025 20:56:08 +0800 (CST) Received: from kwepemq200018.china.huawei.com (7.202.195.108) by dggemv706-chm.china.huawei.com (10.3.19.33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:07 +0800 Received: from localhost.localdomain (10.50.165.33) by kwepemq200018.china.huawei.com (7.202.195.108) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Thu, 19 Jun 2025 20:56:07 +0800 From: Yicong Yang To: , , , CC: , , , , , Subject: [RESEND PATCH v3 8/8] drivers/perf: hisi: Add support for HiSilicon MN PMU driver Date: Thu, 19 Jun 2025 20:55:57 +0800 Message-ID: <20250619125557.57372-9-yangyicong@huawei.com> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20250619125557.57372-1-yangyicong@huawei.com> References: <20250619125557.57372-1-yangyicong@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To kwepemq200018.china.huawei.com (7.202.195.108) Content-Type: text/plain; charset="utf-8" From: Junhao He MN (Miscellaneous Node) is a hybrid node in ARM CHI. It broadcasts the following two types of requests: DVM operations and PCIe configuration. MN PMU devices exist on both SCCL and SICL, so we named the MN pmu driver after SCL (Super cluster) ID. The MN PMU driver using the HiSilicon uncore PMU framework. And only the event parameter is supported. Signed-off-by: Junhao He Reviewed-by: Jonathan Cameron Signed-off-by: Yicong Yang --- drivers/perf/hisilicon/Makefile | 2 +- drivers/perf/hisilicon/hisi_uncore_mn_pmu.c | 355 ++++++++++++++++++++ 2 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 drivers/perf/hisilicon/hisi_uncore_mn_pmu.c diff --git a/drivers/perf/hisilicon/Makefile b/drivers/perf/hisilicon/Makef= ile index dcec8f39719d..186be3d02238 100644 --- a/drivers/perf/hisilicon/Makefile +++ b/drivers/perf/hisilicon/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_HISI_PMU) +=3D hisi_uncore_pmu.o hisi_uncore_l3c_pmu.o \ hisi_uncore_hha_pmu.o hisi_uncore_ddrc_pmu.o hisi_uncore_sllc_pmu.o \ hisi_uncore_pa_pmu.o hisi_uncore_cpa_pmu.o hisi_uncore_uc_pmu.o \ - hisi_uncore_noc_pmu.o + hisi_uncore_noc_pmu.o hisi_uncore_mn_pmu.o =20 obj-$(CONFIG_HISI_PCIE_PMU) +=3D hisi_pcie_pmu.o obj-$(CONFIG_HNS3_PMU) +=3D hns3_pmu.o diff --git a/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c b/drivers/perf/his= ilicon/hisi_uncore_mn_pmu.c new file mode 100644 index 000000000000..bf9b326e40cf --- /dev/null +++ b/drivers/perf/hisilicon/hisi_uncore_mn_pmu.c @@ -0,0 +1,355 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * HiSilicon SoC MN uncore Hardware event counters support + * + * Copyright (c) 2025 HiSilicon Technologies Co., Ltd. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "hisi_uncore_pmu.h" + +/* Dynamic CPU hotplug state used by MN PMU */ +static enum cpuhp_state hisi_mn_pmu_online; + +/* MN register definition */ +#define HISI_MN_DYNAMIC_CTRL 0x400 +#define HISI_MN_DYNAMIC_CTRL_EN BIT(0) +#define HISI_MN_PERF_CTRL_REG 0x408 +#define HISI_MN_PERF_CTRL_EN BIT(6) +#define HISI_MN_INT_MASK_REG 0x800 +#define HISI_MN_INT_STATUS_REG 0x808 +#define HISI_MN_INT_CLEAR_REG 0x80C +#define HISI_MN_EVENT_CTRL_REG 0x1C00 +#define HISI_MN_VERSION_REG 0x1C04 +#define HISI_MN_EVTYPE_REGn(n) (0x1d00 + (n) * 4) +#define HISI_MN_EVTYPE_MASK GENMASK(7, 0) +#define HISI_MN_CNTR_REGn(n) (0x1e00 + (n) * 8) + +#define HISI_MN_NR_COUNTERS 4 +#define HISI_MN_COUNTER_BITS 48 +#define HISI_MN_TIMEOUT_US 500U + +/* + * Each event request takes a certain amount of time to complete. If + * we counting the latency related event, we need to wait for the all + * requests complete. Otherwise, the value of counter is slightly larger. + */ +static void hisi_mn_pmu_counter_flush(struct hisi_pmu *mn_pmu) +{ + int ret; + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_DYNAMIC_CTRL); + val |=3D HISI_MN_DYNAMIC_CTRL_EN; + writel(val, mn_pmu->base + HISI_MN_DYNAMIC_CTRL); + + ret =3D readl_poll_timeout_atomic(mn_pmu->base + HISI_MN_DYNAMIC_CTRL, + val, !(val & HISI_MN_DYNAMIC_CTRL_EN), + 1, HISI_MN_TIMEOUT_US); + if (ret) + dev_warn(mn_pmu->dev, "Counter flush timeout\n"); +} + +static u64 hisi_mn_pmu_read_counter(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc) +{ + return readq(mn_pmu->base + HISI_MN_CNTR_REGn(hwc->idx)); +} + +static void hisi_mn_pmu_write_counter(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc, u64 val) +{ + writeq(val, mn_pmu->base + HISI_MN_CNTR_REGn(hwc->idx)); +} + +static void hisi_mn_pmu_write_evtype(struct hisi_pmu *mn_pmu, int idx, u32= type) +{ + u32 val; + + /* + * Select the appropriate event select register. + * There are 2 32-bit event select registers for the + * 8 hardware counters, each event code is 8-bit wide. + */ + val =3D readl(mn_pmu->base + HISI_MN_EVTYPE_REGn(idx / 4)); + val &=3D ~(HISI_MN_EVTYPE_MASK << HISI_PMU_EVTYPE_SHIFT(idx)); + val |=3D (type << HISI_PMU_EVTYPE_SHIFT(idx)); + writel(val, mn_pmu->base + HISI_MN_EVTYPE_REGn(idx / 4)); +} + +static void hisi_mn_pmu_start_counters(struct hisi_pmu *mn_pmu) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_PERF_CTRL_REG); + val |=3D HISI_MN_PERF_CTRL_EN; + writel(val, mn_pmu->base + HISI_MN_PERF_CTRL_REG); +} + +static void hisi_mn_pmu_stop_counters(struct hisi_pmu *mn_pmu) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_PERF_CTRL_REG); + val &=3D ~HISI_MN_PERF_CTRL_EN; + writel(val, mn_pmu->base + HISI_MN_PERF_CTRL_REG); + + hisi_mn_pmu_counter_flush(mn_pmu); +} + +static void hisi_mn_pmu_enable_counter(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_EVENT_CTRL_REG); + val |=3D BIT(hwc->idx); + writel(val, mn_pmu->base + HISI_MN_EVENT_CTRL_REG); +} + +static void hisi_mn_pmu_disable_counter(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_EVENT_CTRL_REG); + val &=3D ~BIT(hwc->idx); + writel(val, mn_pmu->base + HISI_MN_EVENT_CTRL_REG); +} + +static void hisi_mn_pmu_enable_counter_int(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_INT_MASK_REG); + val &=3D ~BIT(hwc->idx); + writel(val, mn_pmu->base + HISI_MN_INT_MASK_REG); +} + +static void hisi_mn_pmu_disable_counter_int(struct hisi_pmu *mn_pmu, + struct hw_perf_event *hwc) +{ + u32 val; + + val =3D readl(mn_pmu->base + HISI_MN_INT_MASK_REG); + val |=3D BIT(hwc->idx); + writel(val, mn_pmu->base + HISI_MN_INT_MASK_REG); +} + +static u32 hisi_mn_pmu_get_int_status(struct hisi_pmu *mn_pmu) +{ + return readl(mn_pmu->base + HISI_MN_INT_STATUS_REG); +} + +static void hisi_mn_pmu_clear_int_status(struct hisi_pmu *mn_pmu, int idx) +{ + writel(BIT(idx), mn_pmu->base + HISI_MN_INT_CLEAR_REG); +} + +static struct attribute *hisi_mn_pmu_format_attr[] =3D { + HISI_PMU_FORMAT_ATTR(event, "config:0-7"), + NULL +}; + +static const struct attribute_group hisi_mn_pmu_format_group =3D { + .name =3D "format", + .attrs =3D hisi_mn_pmu_format_attr, +}; + +static struct attribute *hisi_mn_pmu_events_attr[] =3D { + HISI_PMU_EVENT_ATTR(req_eobarrier_num, 0x00), + HISI_PMU_EVENT_ATTR(req_ecbarrier_num, 0x01), + HISI_PMU_EVENT_ATTR(req_dvmop_num, 0x02), + HISI_PMU_EVENT_ATTR(req_dvmsync_num, 0x03), + HISI_PMU_EVENT_ATTR(req_retry_num, 0x04), + HISI_PMU_EVENT_ATTR(req_writenosnp_num, 0x05), + HISI_PMU_EVENT_ATTR(req_readnosnp_num, 0x06), + HISI_PMU_EVENT_ATTR(snp_dvm_num, 0x07), + HISI_PMU_EVENT_ATTR(snp_dvmsync_num, 0x08), + HISI_PMU_EVENT_ATTR(l3t_req_dvm_num, 0x09), + HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_num, 0x0A), + HISI_PMU_EVENT_ATTR(mn_req_dvm_num, 0x0B), + HISI_PMU_EVENT_ATTR(mn_req_dvmsync_num, 0x0C), + HISI_PMU_EVENT_ATTR(pa_req_dvm_num, 0x0D), + HISI_PMU_EVENT_ATTR(pa_req_dvmsync_num, 0x0E), + HISI_PMU_EVENT_ATTR(snp_dvm_latency, 0x80), + HISI_PMU_EVENT_ATTR(snp_dvmsync_latency, 0x81), + HISI_PMU_EVENT_ATTR(l3t_req_dvm_latency, 0x82), + HISI_PMU_EVENT_ATTR(l3t_req_dvmsync_latency, 0x83), + HISI_PMU_EVENT_ATTR(mn_req_dvm_latency, 0x84), + HISI_PMU_EVENT_ATTR(mn_req_dvmsync_latency, 0x85), + HISI_PMU_EVENT_ATTR(pa_req_dvm_latency, 0x86), + HISI_PMU_EVENT_ATTR(pa_req_dvmsync_latency, 0x87), + NULL +}; + +static const struct attribute_group hisi_mn_pmu_events_group =3D { + .name =3D "events", + .attrs =3D hisi_mn_pmu_events_attr, +}; + +static const struct attribute_group *hisi_mn_pmu_attr_groups[] =3D { + &hisi_mn_pmu_format_group, + &hisi_mn_pmu_events_group, + &hisi_pmu_cpumask_attr_group, + &hisi_pmu_identifier_group, + NULL +}; + +static const struct hisi_uncore_ops hisi_uncore_mn_ops =3D { + .write_evtype =3D hisi_mn_pmu_write_evtype, + .get_event_idx =3D hisi_uncore_pmu_get_event_idx, + .start_counters =3D hisi_mn_pmu_start_counters, + .stop_counters =3D hisi_mn_pmu_stop_counters, + .enable_counter =3D hisi_mn_pmu_enable_counter, + .disable_counter =3D hisi_mn_pmu_disable_counter, + .enable_counter_int =3D hisi_mn_pmu_enable_counter_int, + .disable_counter_int =3D hisi_mn_pmu_disable_counter_int, + .write_counter =3D hisi_mn_pmu_write_counter, + .read_counter =3D hisi_mn_pmu_read_counter, + .get_int_status =3D hisi_mn_pmu_get_int_status, + .clear_int_status =3D hisi_mn_pmu_clear_int_status, +}; + +static int hisi_mn_pmu_dev_init(struct platform_device *pdev, + struct hisi_pmu *mn_pmu) +{ + int ret; + + hisi_uncore_pmu_init_topology(mn_pmu, &pdev->dev); + + if (mn_pmu->topo.scl_id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Failed to read MN scl id\n"); + + if (mn_pmu->topo.index_id < 0) + return dev_err_probe(&pdev->dev, -EINVAL, + "Failed to read MN index id\n"); + + mn_pmu->base =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mn_pmu->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(mn_pmu->base), + "Failed to ioremap resource\n"); + + ret =3D hisi_uncore_pmu_init_irq(mn_pmu, pdev); + if (ret) + return ret; + + mn_pmu->on_cpu =3D -1; + mn_pmu->dev =3D &pdev->dev; + mn_pmu->ops =3D &hisi_uncore_mn_ops; + mn_pmu->pmu_events.attr_groups =3D hisi_mn_pmu_attr_groups; + mn_pmu->check_event =3D HISI_MN_EVTYPE_MASK; + mn_pmu->num_counters =3D HISI_MN_NR_COUNTERS; + mn_pmu->counter_bits =3D HISI_MN_COUNTER_BITS; + mn_pmu->identifier =3D readl(mn_pmu->base + HISI_MN_VERSION_REG); + return 0; +} + +static void hisi_mn_pmu_remove_cpuhp(void *hotplug_node) +{ + cpuhp_state_remove_instance_nocalls(hisi_mn_pmu_online, hotplug_node); +} + +static void hisi_mn_pmu_unregister(void *pmu) +{ + perf_pmu_unregister(pmu); +} + +static int hisi_mn_pmu_probe(struct platform_device *pdev) +{ + struct hisi_pmu *mn_pmu; + char *name; + int ret; + + mn_pmu =3D devm_kzalloc(&pdev->dev, sizeof(*mn_pmu), GFP_KERNEL); + if (!mn_pmu) + return -ENOMEM; + + platform_set_drvdata(pdev, mn_pmu); + + ret =3D hisi_mn_pmu_dev_init(pdev, mn_pmu); + if (ret) + return ret; + + name =3D devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_scl%d_mn%d", + mn_pmu->topo.scl_id, mn_pmu->topo.index_id); + if (!name) + return -ENOMEM; + + ret =3D cpuhp_state_add_instance(hisi_mn_pmu_online, &mn_pmu->node); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to register cpu hotplug\n"= ); + + ret =3D devm_add_action_or_reset(&pdev->dev, hisi_mn_pmu_remove_cpuhp, &m= n_pmu->node); + if (ret) + return ret; + + hisi_pmu_init(mn_pmu, THIS_MODULE); + + ret =3D perf_pmu_register(&mn_pmu->pmu, name, -1); + if (ret) + return dev_err_probe(mn_pmu->dev, ret, "Failed to register MN PMU\n"); + + return devm_add_action_or_reset(&pdev->dev, hisi_mn_pmu_unregister, &mn_p= mu->pmu); +} + +static const struct acpi_device_id hisi_mn_pmu_acpi_match[] =3D { + { "HISI0222", }, + { } +}; +MODULE_DEVICE_TABLE(acpi, hisi_mn_pmu_acpi_match); + +static struct platform_driver hisi_mn_pmu_driver =3D { + .driver =3D { + .name =3D "hisi_mn_pmu", + .acpi_match_table =3D hisi_mn_pmu_acpi_match, + /* + * We have not worked out a safe bind/unbind process, + * Forcefully unbinding during sampling will lead to a + * kernel panic, so this is not supported yet. + */ + .suppress_bind_attrs =3D true, + }, + .probe =3D hisi_mn_pmu_probe, +}; + +static int __init hisi_mn_pmu_module_init(void) +{ + int ret; + + ret =3D cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, "perf/hisi/mn:online= ", + hisi_uncore_pmu_online_cpu, + hisi_uncore_pmu_offline_cpu); + if (ret < 0) { + pr_err("hisi_mn_pmu: Failed to setup MN PMU hotplug: %d\n", ret); + return ret; + } + hisi_mn_pmu_online =3D ret; + + ret =3D platform_driver_register(&hisi_mn_pmu_driver); + if (ret) + cpuhp_remove_multi_state(hisi_mn_pmu_online); + + return ret; +} +module_init(hisi_mn_pmu_module_init); + +static void __exit hisi_mn_pmu_module_exit(void) +{ + platform_driver_unregister(&hisi_mn_pmu_driver); + cpuhp_remove_multi_state(hisi_mn_pmu_online); +} +module_exit(hisi_mn_pmu_module_exit); + +MODULE_IMPORT_NS("HISI_PMU"); +MODULE_DESCRIPTION("HiSilicon SoC MN uncore PMU driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Junhao He "); --=20 2.24.0