Skip to content

Commit 1ad3f70

Browse files
jic23djbw
authored andcommitted
cxl/pci: Find and register CXL PMU devices
CXL PMU devices can be found from entries in the Register Locator DVSEC. Reviewed-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Link: https://lore.kernel.org/r/20230526095824.16336-4-Jonathan.Cameron@huawei.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
1 parent d717d7f commit 1ad3f70

10 files changed

Lines changed: 156 additions & 1 deletion

File tree

drivers/cxl/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ cxl_core-y += memdev.o
1212
cxl_core-y += mbox.o
1313
cxl_core-y += pci.o
1414
cxl_core-y += hdm.o
15+
cxl_core-y += pmu.o
1516
cxl_core-$(CONFIG_TRACING) += trace.o
1617
cxl_core-$(CONFIG_CXL_REGION) += region.o

drivers/cxl/core/core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
extern const struct device_type cxl_nvdimm_bridge_type;
88
extern const struct device_type cxl_nvdimm_type;
9+
extern const struct device_type cxl_pmu_type;
910

1011
extern struct attribute_group cxl_base_attribute_group;
1112

drivers/cxl/core/pmu.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright(c) 2023 Huawei. All rights reserved. */
3+
4+
#include <linux/device.h>
5+
#include <linux/slab.h>
6+
#include <linux/idr.h>
7+
#include <cxlmem.h>
8+
#include <pmu.h>
9+
#include <cxl.h>
10+
#include "core.h"
11+
12+
static void cxl_pmu_release(struct device *dev)
13+
{
14+
struct cxl_pmu *pmu = to_cxl_pmu(dev);
15+
16+
kfree(pmu);
17+
}
18+
19+
const struct device_type cxl_pmu_type = {
20+
.name = "cxl_pmu",
21+
.release = cxl_pmu_release,
22+
};
23+
24+
static void remove_dev(void *dev)
25+
{
26+
device_del(dev);
27+
}
28+
29+
int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
30+
int assoc_id, int index, enum cxl_pmu_type type)
31+
{
32+
struct cxl_pmu *pmu;
33+
struct device *dev;
34+
int rc;
35+
36+
pmu = kzalloc(sizeof(*pmu), GFP_KERNEL);
37+
if (!pmu)
38+
return -ENOMEM;
39+
40+
pmu->assoc_id = assoc_id;
41+
pmu->index = index;
42+
pmu->type = type;
43+
pmu->base = regs->pmu;
44+
dev = &pmu->dev;
45+
device_initialize(dev);
46+
device_set_pm_not_required(dev);
47+
dev->parent = parent;
48+
dev->bus = &cxl_bus_type;
49+
dev->type = &cxl_pmu_type;
50+
switch (pmu->type) {
51+
case CXL_PMU_MEMDEV:
52+
rc = dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index);
53+
break;
54+
}
55+
if (rc)
56+
goto err;
57+
58+
rc = device_add(dev);
59+
if (rc)
60+
goto err;
61+
62+
return devm_add_action_or_reset(parent, remove_dev, dev);
63+
64+
err:
65+
put_device(&pmu->dev);
66+
return rc;
67+
}
68+
EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL);

drivers/cxl/core/port.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev)
5656
return CXL_DEVICE_MEMORY_EXPANDER;
5757
if (dev->type == CXL_REGION_TYPE())
5858
return CXL_DEVICE_REGION;
59+
if (dev->type == &cxl_pmu_type)
60+
return CXL_DEVICE_PMU;
5961
return 0;
6062
}
6163

drivers/cxl/core/regs.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/pci.h>
77
#include <cxlmem.h>
88
#include <cxlpci.h>
9+
#include <pmu.h>
910

1011
#include "core.h"
1112

@@ -379,6 +380,21 @@ int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
379380
}
380381
EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
381382

383+
int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
384+
struct cxl_register_map *map)
385+
{
386+
struct device *dev = &pdev->dev;
387+
resource_size_t phys_addr;
388+
389+
phys_addr = map->resource;
390+
regs->pmu = devm_cxl_iomap_block(dev, phys_addr, CXL_PMU_REGMAP_SIZE);
391+
if (!regs->pmu)
392+
return -ENOMEM;
393+
394+
return 0;
395+
}
396+
EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL);
397+
382398
resource_size_t cxl_rcrb_to_component(struct device *dev,
383399
resource_size_t rcrb,
384400
enum cxl_rcrb which)

drivers/cxl/cxl.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,10 @@ struct cxl_regs {
209209
struct_group_tagged(cxl_device_regs, device_regs,
210210
void __iomem *status, *mbox, *memdev;
211211
);
212+
213+
struct_group_tagged(cxl_pmu_regs, pmu_regs,
214+
void __iomem *pmu;
215+
);
212216
};
213217

214218
struct cxl_reg_map {
@@ -229,6 +233,10 @@ struct cxl_device_reg_map {
229233
struct cxl_reg_map memdev;
230234
};
231235

236+
struct cxl_pmu_reg_map {
237+
struct cxl_reg_map pmu;
238+
};
239+
232240
/**
233241
* struct cxl_register_map - DVSEC harvested register block mapping parameters
234242
* @base: virtual base of the register-block-BAR + @block_offset
@@ -237,6 +245,7 @@ struct cxl_device_reg_map {
237245
* @reg_type: see enum cxl_regloc_type
238246
* @component_map: cxl_reg_map for component registers
239247
* @device_map: cxl_reg_maps for device registers
248+
* @pmu_map: cxl_reg_maps for CXL Performance Monitoring Units
240249
*/
241250
struct cxl_register_map {
242251
void __iomem *base;
@@ -246,6 +255,7 @@ struct cxl_register_map {
246255
union {
247256
struct cxl_component_reg_map component_map;
248257
struct cxl_device_reg_map device_map;
258+
struct cxl_pmu_reg_map pmu_map;
249259
};
250260
};
251261

@@ -258,6 +268,8 @@ int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
258268
unsigned long map_mask);
259269
int cxl_map_device_regs(struct device *dev, struct cxl_device_regs *regs,
260270
struct cxl_register_map *map);
271+
int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
272+
struct cxl_register_map *map);
261273

262274
enum cxl_regloc_type;
263275
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
@@ -753,6 +765,7 @@ void cxl_driver_unregister(struct cxl_driver *cxl_drv);
753765
#define CXL_DEVICE_REGION 6
754766
#define CXL_DEVICE_PMEM_REGION 7
755767
#define CXL_DEVICE_DAX_REGION 8
768+
#define CXL_DEVICE_PMU 9
756769

757770
#define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*")
758771
#define CXL_MODALIAS_FMT "cxl:t%d"

drivers/cxl/cxlpci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ enum cxl_regloc_type {
6767
CXL_REGLOC_RBI_COMPONENT,
6868
CXL_REGLOC_RBI_VIRT,
6969
CXL_REGLOC_RBI_MEMDEV,
70+
CXL_REGLOC_RBI_PMU,
7071
CXL_REGLOC_RBI_TYPES
7172
};
7273

drivers/cxl/pci.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "cxlmem.h"
1414
#include "cxlpci.h"
1515
#include "cxl.h"
16+
#include "pmu.h"
1617

1718
/**
1819
* DOC: cxl pci
@@ -657,7 +658,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
657658
struct cxl_register_map map;
658659
struct cxl_memdev *cxlmd;
659660
struct cxl_dev_state *cxlds;
660-
int rc;
661+
int i, rc, pmu_count;
661662

662663
/*
663664
* Double check the anonymous union trickery in struct cxl_regs
@@ -746,6 +747,29 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
746747
if (IS_ERR(cxlmd))
747748
return PTR_ERR(cxlmd);
748749

750+
pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
751+
for (i = 0; i < pmu_count; i++) {
752+
struct cxl_pmu_regs pmu_regs;
753+
754+
rc = cxl_find_regblock_instance(pdev, CXL_REGLOC_RBI_PMU, &map, i);
755+
if (rc) {
756+
dev_dbg(&pdev->dev, "Could not find PMU regblock\n");
757+
break;
758+
}
759+
760+
rc = cxl_map_pmu_regs(pdev, &pmu_regs, &map);
761+
if (rc) {
762+
dev_dbg(&pdev->dev, "Could not map PMU regs\n");
763+
break;
764+
}
765+
766+
rc = devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEMDEV);
767+
if (rc) {
768+
dev_dbg(&pdev->dev, "Could not add PMU instance\n");
769+
break;
770+
}
771+
}
772+
749773
rc = cxl_event_config(host_bridge, cxlds);
750774
if (rc)
751775
return rc;

drivers/cxl/pmu.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright(c) 2023 Huawei
4+
* CXL Specification rev 3.0 Setion 8.2.7 (CPMU Register Interface)
5+
*/
6+
#ifndef CXL_PMU_H
7+
#define CXL_PMU_H
8+
#include <linux/device.h>
9+
10+
enum cxl_pmu_type {
11+
CXL_PMU_MEMDEV,
12+
};
13+
14+
#define CXL_PMU_REGMAP_SIZE 0xe00 /* Table 8-32 CXL 3.0 specification */
15+
struct cxl_pmu {
16+
struct device dev;
17+
void __iomem *base;
18+
int assoc_id;
19+
int index;
20+
enum cxl_pmu_type type;
21+
};
22+
23+
#define to_cxl_pmu(dev) container_of(dev, struct cxl_pmu, dev)
24+
struct cxl_pmu_regs;
25+
int devm_cxl_pmu_add(struct device *parent, struct cxl_pmu_regs *regs,
26+
int assoc_id, int idx, enum cxl_pmu_type type);
27+
28+
#endif

tools/testing/cxl/Kbuild

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ cxl_core-y += $(CXL_CORE_SRC)/memdev.o
5757
cxl_core-y += $(CXL_CORE_SRC)/mbox.o
5858
cxl_core-y += $(CXL_CORE_SRC)/pci.o
5959
cxl_core-y += $(CXL_CORE_SRC)/hdm.o
60+
cxl_core-y += $(CXL_CORE_SRC)/pmu.o
6061
cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
6162
cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
6263
cxl_core-y += config_check.o

0 commit comments

Comments
 (0)