Commit 1ad3f701 authored by Jonathan Cameron's avatar Jonathan Cameron Committed by Dan Williams
Browse files

cxl/pci: Find and register CXL PMU devices



CXL PMU devices can be found from entries in the Register
Locator DVSEC.

Reviewed-by: default avatarDan Williams <dan.j.williams@intel.com>
Reviewed-by: default avatarDave Jiang <dave.jiang@intel.com>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/20230526095824.16336-4-Jonathan.Cameron@huawei.com


Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent d717d7f3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
@@ -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;

drivers/cxl/core/pmu.c

0 → 100644
+68 −0
Original line number Diff line number Diff line
// 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 −0
Original line number Diff line number Diff line
@@ -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;
}

+16 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <cxlmem.h>
#include <cxlpci.h>
#include <pmu.h>

#include "core.h"

@@ -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)
Loading