From nobody Thu Oct 31 00:21:16 2024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5A535C77B73 for ; Wed, 31 May 2023 11:02:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235304AbjEaLCj (ORCPT ); Wed, 31 May 2023 07:02:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53300 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235298AbjEaLCI (ORCPT ); Wed, 31 May 2023 07:02:08 -0400 Received: from frasgout.his.huawei.com (frasgout.his.huawei.com [185.176.79.56]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AA07CE6C; Wed, 31 May 2023 04:01:43 -0700 (PDT) Received: from lhrpeml500005.china.huawei.com (unknown [172.18.147.207]) by frasgout.his.huawei.com (SkyGuard) with ESMTP id 4QWR640QHZz6J7f1; Wed, 31 May 2023 18:56:44 +0800 (CST) Received: from SecurePC-101-06.china.huawei.com (10.122.247.231) by lhrpeml500005.china.huawei.com (7.191.163.240) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23; Wed, 31 May 2023 12:01:41 +0100 From: Jonathan Cameron To: Namhyung Kim , Liang Kan , , CC: , , , , , , , , Davidlohr Bueso , Dave Jiang Subject: [PATCH v8 3/5] cxl/pci: Find and register CXL PMU devices Date: Wed, 31 May 2023 12:00:09 +0100 Message-ID: <20230531110011.13963-4-Jonathan.Cameron@huawei.com> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230531110011.13963-1-Jonathan.Cameron@huawei.com> References: <20230531110011.13963-1-Jonathan.Cameron@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.122.247.231] X-ClientProxiedBy: lhrpeml500005.china.huawei.com (7.191.163.240) To lhrpeml500005.china.huawei.com (7.191.163.240) X-CFilter-Loop: Reflected Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" CXL PMU devices can be found from entries in the Register Locator DVSEC. Reviewed-by: Dan Williams Reviewed-by: Dave Jiang Signed-off-by: Jonathan Cameron --- drivers/cxl/core/Makefile | 1 + drivers/cxl/core/core.h | 1 + drivers/cxl/core/pmu.c | 68 +++++++++++++++++++++++++++++++++++++++ drivers/cxl/core/port.c | 2 ++ drivers/cxl/core/regs.c | 16 +++++++++ drivers/cxl/cxl.h | 13 ++++++++ drivers/cxl/cxlpci.h | 1 + drivers/cxl/pci.c | 26 ++++++++++++++- drivers/cxl/pmu.h | 28 ++++++++++++++++ 9 files changed, 155 insertions(+), 1 deletion(-) diff --git a/drivers/cxl/core/Makefile b/drivers/cxl/core/Makefile index ca4ae31d8f57..1f66b5d4d935 100644 --- a/drivers/cxl/core/Makefile +++ b/drivers/cxl/core/Makefile @@ -12,5 +12,6 @@ cxl_core-y +=3D memdev.o cxl_core-y +=3D mbox.o cxl_core-y +=3D pci.o cxl_core-y +=3D hdm.o +cxl_core-y +=3D pmu.o cxl_core-$(CONFIG_TRACING) +=3D trace.o cxl_core-$(CONFIG_CXL_REGION) +=3D region.o diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h index 27f0968449de..99d4a967eca6 100644 --- a/drivers/cxl/core/core.h +++ b/drivers/cxl/core/core.h @@ -6,6 +6,7 @@ =20 extern const struct device_type cxl_nvdimm_bridge_type; extern const struct device_type cxl_nvdimm_type; +extern const struct device_type cxl_pmu_type; =20 extern struct attribute_group cxl_base_attribute_group; =20 diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c new file mode 100644 index 000000000000..7684c843e5a5 --- /dev/null +++ b/drivers/cxl/core/pmu.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Huawei. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include "core.h" + +static void cxl_pmu_release(struct device *dev) +{ + struct cxl_pmu *pmu =3D to_cxl_pmu(dev); + + kfree(pmu); +} + +const struct device_type cxl_pmu_type =3D { + .name =3D "cxl_pmu", + .release =3D cxl_pmu_release, +}; + +static void remove_dev(void *dev) +{ + device_del(dev); +} + +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int index, enum cxl_pmu_type type) +{ + struct cxl_pmu *pmu; + struct device *dev; + int rc; + + pmu =3D kzalloc(sizeof(*pmu), GFP_KERNEL); + if (!pmu) + return -ENOMEM; + + pmu->assoc_id =3D assoc_id; + pmu->index =3D index; + pmu->type =3D type; + pmu->base =3D regs->pmu; + dev =3D &pmu->dev; + device_initialize(dev); + device_set_pm_not_required(dev); + dev->parent =3D parent; + dev->bus =3D &cxl_bus_type; + dev->type =3D &cxl_pmu_type; + switch (pmu->type) { + case CXL_PMU_MEMDEV: + rc =3D dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index); + break; + } + if (rc) + goto err; + + rc =3D device_add(dev); + if (rc) + goto err; + + return devm_add_action_or_reset(parent, remove_dev, dev); + +err: + put_device(&pmu->dev); + return rc; +} +EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL); diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index da2068475fa2..eee1fcb9199b 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev) return CXL_DEVICE_MEMORY_EXPANDER; if (dev->type =3D=3D CXL_REGION_TYPE()) return CXL_DEVICE_REGION; + if (dev->type =3D=3D &cxl_pmu_type) + return CXL_DEVICE_PMU; return 0; } =20 diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 4b9672db867d..518bc2ad2c1e 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -6,6 +6,7 @@ #include #include #include +#include =20 #include "core.h" =20 @@ -379,6 +380,21 @@ int cxl_count_regblock(struct pci_dev *pdev, enum cxl_= regloc_type type) } EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL); =20 +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map) +{ + struct device *dev =3D &pdev->dev; + resource_size_t phys_addr; + + phys_addr =3D map->resource; + regs->pmu =3D devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE); + if (!regs->pmu) + return -ENOMEM; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL); + resource_size_t cxl_rcrb_to_component(struct device *dev, resource_size_t rcrb, enum cxl_rcrb which) diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index f6e2a9ea5f41..610aa430276b 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -209,6 +209,10 @@ struct cxl_regs { struct_group_tagged(cxl_device_regs, device_regs, void __iomem *status, *mbox, *memdev; ); + + struct_group_tagged(cxl_pmu_regs, pmu_regs, + void __iomem *pmu; + ); }; =20 struct cxl_reg_map { @@ -229,6 +233,10 @@ struct cxl_device_reg_map { struct cxl_reg_map memdev; }; =20 +struct cxl_pmu_reg_map { + struct cxl_reg_map pmu; +}; + /** * struct cxl_register_map - DVSEC harvested register block mapping parame= ters * @base: virtual base of the register-block-BAR + @block_offset @@ -237,6 +245,7 @@ struct cxl_device_reg_map { * @reg_type: see enum cxl_regloc_type * @component_map: cxl_reg_map for component registers * @device_map: cxl_reg_maps for device registers + * @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units */ struct cxl_register_map { void __iomem *base; @@ -246,6 +255,7 @@ struct cxl_register_map { union { struct cxl_component_reg_map component_map; struct cxl_device_reg_map device_map; + struct cxl_pmu_reg_map pmu_map; }; }; =20 @@ -258,6 +268,8 @@ int cxl_map_component_regs(struct device *dev, struct c= xl_component_regs *regs, unsigned long map_mask); int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs, struct cxl_register_map *map); +int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs, + struct cxl_register_map *map); =20 enum cxl_regloc_type; int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type); @@ -752,6 +764,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv); #define CXL_DEVICE_REGION 6 #define CXL_DEVICE_PMEM_REGION 7 #define CXL_DEVICE_DAX_REGION 8 +#define CXL_DEVICE_PMU 9 =20 #define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*") #define CXL_MODALIAS_FMT "cxl:t%d" diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 0465ef963cd6..b1bbf69b62c5 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -65,6 +65,7 @@ enum cxl_regloc_type { CXL_REGLOC_RBI_COMPONENT, CXL_REGLOC_RBI_VIRT, CXL_REGLOC_RBI_MEMDEV, + CXL_REGLOC_RBI_PMU, CXL_REGLOC_RBI_TYPES }; =20 diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index f7a5b8e9c102..2ad043d77975 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -13,6 +13,7 @@ #include "cxlmem.h" #include "cxlpci.h" #include "cxl.h" +#include "pmu.h" =20 /** * DOC: cxl pci @@ -657,7 +658,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const st= ruct pci_device_id *id) struct cxl_register_map map; struct cxl_memdev *cxlmd; struct cxl_dev_state *cxlds; - int rc; + int i, rc, pmu_count; =20 /* * Double check the anonymous union trickery in struct cxl_regs @@ -740,6 +741,29 @@ static int cxl_pci_probe(struct pci_dev *pdev, const s= truct pci_device_id *id) if (IS_ERR(cxlmd)) return PTR_ERR(cxlmd); =20 + pmu_count =3D cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU); + for (i =3D 0; i < pmu_count; i++) { + struct cxl_pmu_regs pmu_regs; + + rc =3D cxl_find_regblock_instance(pdev, CXL_REGLOC_RBI_PMU, &map, i); + if (rc) { + dev_dbg(&pdev->dev, "Could not find PMU regblock\n"); + break; + } + + rc =3D cxl_map_pmu_regs(pdev, &pmu_regs, &map); + if (rc) { + dev_dbg(&pdev->dev, "Could not map PMU regs\n"); + break; + } + + rc =3D devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEM= DEV); + if (rc) { + dev_dbg(&pdev->dev, "Could not add PMU instance\n"); + break; + } + } + rc =3D cxl_event_config(host_bridge, cxlds); if (rc) return rc; diff --git a/drivers/cxl/pmu.h b/drivers/cxl/pmu.h new file mode 100644 index 000000000000..b1e9bcd9f28c --- /dev/null +++ b/drivers/cxl/pmu.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Huawei + * CXL Specification rev 3.0 Setion 8.2.7 (CPMU Register Interface) + */ +#ifndef CXL_PMU_H +#define CXL_PMU_H +#include + +enum cxl_pmu_type { + CXL_PMU_MEMDEV, +}; + +#define CXL_PMU_REGMAP_SIZE 0xe00 /* Table 8-32 CXL 3.0 specification */ +struct cxl_pmu { + struct device dev; + void __iomem *base; + int assoc_id; + int index; + enum cxl_pmu_type type; +}; + +#define to_cxl_pmu(dev) container_of(dev, struct cxl_pmu, dev) +struct cxl_pmu_regs; +int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs, + int assoc_id, int idx, enum cxl_pmu_type type); + +#endif --=20 2.39.2