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 12static void cxl_pmu_release(struct device *dev) 13{ 14 struct cxl_pmu *pmu = to_cxl_pmu(dev); 15 16 kfree(pmu); 17} 18 19const struct device_type cxl_pmu_type = { 20 .name = "cxl_pmu", 21 .release = cxl_pmu_release, 22}; 23 24static void remove_dev(void *dev) 25{ 26 device_unregister(dev); 27} 28 29int 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 64err: 65 put_device(&pmu->dev); 66 return rc; 67} 68EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL); 69