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); 69