Skip to content

Commit

Permalink
cxl/pci: Find and register CXL PMU devices
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jonathan Cameron authored and Dan Williams committed May 30, 2023
1 parent d717d7f commit 1ad3f70
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 1 deletion.
1 change: 1 addition & 0 deletions drivers/cxl/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ cxl_core-y += memdev.o
cxl_core-y += mbox.o
cxl_core-y += pci.o
cxl_core-y += hdm.o
cxl_core-y += pmu.o
cxl_core-$(CONFIG_TRACING) += trace.o
cxl_core-$(CONFIG_CXL_REGION) += region.o
1 change: 1 addition & 0 deletions drivers/cxl/core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

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;

extern struct attribute_group cxl_base_attribute_group;

Expand Down
68 changes: 68 additions & 0 deletions drivers/cxl/core/pmu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2023 Huawei. All rights reserved. */

#include <linux/device.h>
#include <linux/slab.h>
#include <linux/idr.h>
#include <cxlmem.h>
#include <pmu.h>
#include <cxl.h>
#include "core.h"

static void cxl_pmu_release(struct device *dev)
{
struct cxl_pmu *pmu = to_cxl_pmu(dev);

kfree(pmu);
}

const struct device_type cxl_pmu_type = {
.name = "cxl_pmu",
.release = 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 = kzalloc(sizeof(*pmu), GFP_KERNEL);
if (!pmu)
return -ENOMEM;

pmu->assoc_id = assoc_id;
pmu->index = index;
pmu->type = type;
pmu->base = regs->pmu;
dev = &pmu->dev;
device_initialize(dev);
device_set_pm_not_required(dev);
dev->parent = parent;
dev->bus = &cxl_bus_type;
dev->type = &cxl_pmu_type;
switch (pmu->type) {
case CXL_PMU_MEMDEV:
rc = dev_set_name(dev, "pmu_mem%d.%d", assoc_id, index);
break;
}
if (rc)
goto err;

rc = 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);
2 changes: 2 additions & 0 deletions drivers/cxl/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ static int cxl_device_id(const struct device *dev)
return CXL_DEVICE_MEMORY_EXPANDER;
if (dev->type == CXL_REGION_TYPE())
return CXL_DEVICE_REGION;
if (dev->type == &cxl_pmu_type)
return CXL_DEVICE_PMU;
return 0;
}

Expand Down
16 changes: 16 additions & 0 deletions drivers/cxl/core/regs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <cxlmem.h>
#include <cxlpci.h>
#include <pmu.h>

#include "core.h"

Expand Down Expand Up @@ -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);

int cxl_map_pmu_regs(struct pci_dev *pdev, struct cxl_pmu_regs *regs,
struct cxl_register_map *map)
{
struct device *dev = &pdev->dev;
resource_size_t phys_addr;

phys_addr = map->resource;
regs->pmu = 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)
Expand Down
13 changes: 13 additions & 0 deletions drivers/cxl/cxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
);
};

struct cxl_reg_map {
Expand All @@ -229,6 +233,10 @@ struct cxl_device_reg_map {
struct cxl_reg_map memdev;
};

struct cxl_pmu_reg_map {
struct cxl_reg_map pmu;
};

/**
* struct cxl_register_map - DVSEC harvested register block mapping parameters
* @base: virtual base of the register-block-BAR + @block_offset
Expand All @@ -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;
Expand All @@ -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;
};
};

Expand All @@ -258,6 +268,8 @@ int cxl_map_component_regs(struct device *dev, struct cxl_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);

enum cxl_regloc_type;
int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type);
Expand Down Expand Up @@ -753,6 +765,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

#define MODULE_ALIAS_CXL(type) MODULE_ALIAS("cxl:t" __stringify(type) "*")
#define CXL_MODALIAS_FMT "cxl:t%d"
Expand Down
1 change: 1 addition & 0 deletions drivers/cxl/cxlpci.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,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
};

Expand Down
26 changes: 25 additions & 1 deletion drivers/cxl/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "cxlmem.h"
#include "cxlpci.h"
#include "cxl.h"
#include "pmu.h"

/**
* DOC: cxl pci
Expand Down Expand Up @@ -657,7 +658,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct 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;

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

pmu_count = cxl_count_regblock(pdev, CXL_REGLOC_RBI_PMU);
for (i = 0; i < pmu_count; i++) {
struct cxl_pmu_regs pmu_regs;

rc = 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 = cxl_map_pmu_regs(pdev, &pmu_regs, &map);
if (rc) {
dev_dbg(&pdev->dev, "Could not map PMU regs\n");
break;
}

rc = devm_cxl_pmu_add(cxlds->dev, &pmu_regs, cxlmd->id, i, CXL_PMU_MEMDEV);
if (rc) {
dev_dbg(&pdev->dev, "Could not add PMU instance\n");
break;
}
}

rc = cxl_event_config(host_bridge, cxlds);
if (rc)
return rc;
Expand Down
28 changes: 28 additions & 0 deletions drivers/cxl/pmu.h
Original file line number Diff line number Diff line change
@@ -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 <linux/device.h>

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
1 change: 1 addition & 0 deletions tools/testing/cxl/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ cxl_core-y += $(CXL_CORE_SRC)/memdev.o
cxl_core-y += $(CXL_CORE_SRC)/mbox.o
cxl_core-y += $(CXL_CORE_SRC)/pci.o
cxl_core-y += $(CXL_CORE_SRC)/hdm.o
cxl_core-y += $(CXL_CORE_SRC)/pmu.o
cxl_core-$(CONFIG_TRACING) += $(CXL_CORE_SRC)/trace.o
cxl_core-$(CONFIG_CXL_REGION) += $(CXL_CORE_SRC)/region.o
cxl_core-y += config_check.o
Expand Down

0 comments on commit 1ad3f70

Please sign in to comment.