1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2025 Arm Ltd. 3 4 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 5 6 #include <linux/acpi.h> 7 #include <linux/arm_mpam.h> 8 #include <linux/cacheinfo.h> 9 #include <linux/cpumask.h> 10 #include <linux/device.h> 11 #include <linux/errno.h> 12 #include <linux/gfp.h> 13 #include <linux/list.h> 14 #include <linux/lockdep.h> 15 #include <linux/mutex.h> 16 #include <linux/platform_device.h> 17 #include <linux/printk.h> 18 #include <linux/srcu.h> 19 #include <linux/types.h> 20 21 #include "mpam_internal.h" 22 23 /* 24 * mpam_list_lock protects the SRCU lists when writing. Once the 25 * mpam_enabled key is enabled these lists are read-only, 26 * unless the error interrupt disables the driver. 27 */ 28 static DEFINE_MUTEX(mpam_list_lock); 29 static LIST_HEAD(mpam_all_msc); 30 31 struct srcu_struct mpam_srcu; 32 33 /* 34 * Number of MSCs that have been probed. Once all MSCs have been probed MPAM 35 * can be enabled. 36 */ 37 static atomic_t mpam_num_msc; 38 39 /* 40 * An MSC can control traffic from a set of CPUs, but may only be accessible 41 * from a (hopefully wider) set of CPUs. The common reason for this is power 42 * management. If all the CPUs in a cluster are in PSCI:CPU_SUSPEND, the 43 * corresponding cache may also be powered off. By making accesses from 44 * one of those CPUs, we ensure we don't access a cache that's powered off. 45 */ 46 static void update_msc_accessibility(struct mpam_msc *msc) 47 { 48 u32 affinity_id; 49 int err; 50 51 err = device_property_read_u32(&msc->pdev->dev, "cpu_affinity", 52 &affinity_id); 53 if (err) 54 cpumask_copy(&msc->accessibility, cpu_possible_mask); 55 else 56 acpi_pptt_get_cpus_from_container(affinity_id, &msc->accessibility); 57 } 58 59 static void mpam_msc_destroy(struct mpam_msc *msc) 60 { 61 struct platform_device *pdev = msc->pdev; 62 63 lockdep_assert_held(&mpam_list_lock); 64 65 list_del_rcu(&msc->all_msc_list); 66 platform_set_drvdata(pdev, NULL); 67 } 68 69 static void mpam_msc_drv_remove(struct platform_device *pdev) 70 { 71 struct mpam_msc *msc = platform_get_drvdata(pdev); 72 73 mutex_lock(&mpam_list_lock); 74 mpam_msc_destroy(msc); 75 mutex_unlock(&mpam_list_lock); 76 77 synchronize_srcu(&mpam_srcu); 78 } 79 80 static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev) 81 { 82 int err; 83 u32 tmp; 84 struct mpam_msc *msc; 85 struct resource *msc_res; 86 struct device *dev = &pdev->dev; 87 88 lockdep_assert_held(&mpam_list_lock); 89 90 msc = devm_kzalloc(&pdev->dev, sizeof(*msc), GFP_KERNEL); 91 if (!msc) 92 return ERR_PTR(-ENOMEM); 93 94 err = devm_mutex_init(dev, &msc->probe_lock); 95 if (err) 96 return ERR_PTR(err); 97 98 err = devm_mutex_init(dev, &msc->part_sel_lock); 99 if (err) 100 return ERR_PTR(err); 101 102 msc->id = pdev->id; 103 msc->pdev = pdev; 104 INIT_LIST_HEAD_RCU(&msc->all_msc_list); 105 INIT_LIST_HEAD_RCU(&msc->ris); 106 107 update_msc_accessibility(msc); 108 if (cpumask_empty(&msc->accessibility)) { 109 dev_err_once(dev, "MSC is not accessible from any CPU!"); 110 return ERR_PTR(-EINVAL); 111 } 112 113 if (device_property_read_u32(&pdev->dev, "pcc-channel", &tmp)) 114 msc->iface = MPAM_IFACE_MMIO; 115 else 116 msc->iface = MPAM_IFACE_PCC; 117 118 if (msc->iface == MPAM_IFACE_MMIO) { 119 void __iomem *io; 120 121 io = devm_platform_get_and_ioremap_resource(pdev, 0, 122 &msc_res); 123 if (IS_ERR(io)) { 124 dev_err_once(dev, "Failed to map MSC base address\n"); 125 return ERR_CAST(io); 126 } 127 msc->mapped_hwpage_sz = msc_res->end - msc_res->start; 128 msc->mapped_hwpage = io; 129 } else { 130 return ERR_PTR(-EINVAL); 131 } 132 133 list_add_rcu(&msc->all_msc_list, &mpam_all_msc); 134 platform_set_drvdata(pdev, msc); 135 136 return msc; 137 } 138 139 static int fw_num_msc; 140 141 static int mpam_msc_drv_probe(struct platform_device *pdev) 142 { 143 int err; 144 struct mpam_msc *msc = NULL; 145 void *plat_data = pdev->dev.platform_data; 146 147 mutex_lock(&mpam_list_lock); 148 msc = do_mpam_msc_drv_probe(pdev); 149 mutex_unlock(&mpam_list_lock); 150 151 if (IS_ERR(msc)) 152 return PTR_ERR(msc); 153 154 /* Create RIS entries described by firmware */ 155 err = acpi_mpam_parse_resources(msc, plat_data); 156 if (err) { 157 mpam_msc_drv_remove(pdev); 158 return err; 159 } 160 161 if (atomic_add_return(1, &mpam_num_msc) == fw_num_msc) 162 pr_info("Discovered all MSCs\n"); 163 164 return 0; 165 } 166 167 static struct platform_driver mpam_msc_driver = { 168 .driver = { 169 .name = "mpam_msc", 170 }, 171 .probe = mpam_msc_drv_probe, 172 .remove = mpam_msc_drv_remove, 173 }; 174 175 static int __init mpam_msc_driver_init(void) 176 { 177 if (!system_supports_mpam()) 178 return -EOPNOTSUPP; 179 180 init_srcu_struct(&mpam_srcu); 181 182 fw_num_msc = acpi_mpam_count_msc(); 183 if (fw_num_msc <= 0) { 184 pr_err("No MSC devices found in firmware\n"); 185 return -EINVAL; 186 } 187 188 return platform_driver_register(&mpam_msc_driver); 189 } 190 subsys_initcall(mpam_msc_driver_init); 191