1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright(c) 2026 Intel Corporation */ 3 #include <linux/sysfs.h> 4 #include <linux/types.h> 5 6 #include "adf_cfg.h" 7 #include "adf_cfg_services.h" 8 #include "adf_common_drv.h" 9 #include "adf_kpt.h" 10 #include "adf_sysfs_kpt.h" 11 12 static ssize_t enable_show(struct device *dev, struct device_attribute *attr, 13 char *buf) 14 { 15 struct adf_kpt_interface_data *user_data; 16 struct adf_accel_dev *accel_dev; 17 18 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 19 if (!accel_dev) 20 return -EINVAL; 21 22 user_data = GET_KPT_USER_DATA(accel_dev); 23 24 return sysfs_emit(buf, "%d\n", user_data->enable); 25 } 26 27 static ssize_t enable_store(struct device *dev, struct device_attribute *attr, 28 const char *buf, size_t count) 29 { 30 struct adf_kpt_interface_data *user_data; 31 struct adf_hw_device_data *hw_data; 32 struct adf_accel_dev *accel_dev; 33 bool enable; 34 int ret; 35 36 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 37 if (!accel_dev) 38 return -EINVAL; 39 40 if (adf_dev_started(accel_dev)) { 41 dev_info(dev, "Device qat_dev%d must be down before enabling KPT\n", 42 accel_dev->accel_id); 43 return -EINVAL; 44 } 45 46 if (adf_get_service_enabled(accel_dev) != SVC_ASYM) { 47 dev_info(dev, "KPT can only be enabled when the asymmetric service is enabled\n"); 48 return -EINVAL; 49 } 50 51 hw_data = GET_HW_DATA(accel_dev); 52 53 /* 54 * Restore the KPT capability bit in the device's capabilities mask 55 * before processing user input, as the bit may have been cleared if 56 * KPT was previously disabled by the user. 57 */ 58 hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev); 59 if (!hw_data->accel_capabilities_mask) 60 return -EINVAL; 61 62 ret = kstrtobool(buf, &enable); 63 if (ret) 64 return ret; 65 66 user_data = GET_KPT_USER_DATA(accel_dev); 67 user_data->enable = enable; 68 69 return count; 70 } 71 static DEVICE_ATTR_RW(enable); 72 73 static ssize_t swk_shared_show(struct device *dev, 74 struct device_attribute *attr, char *buf) 75 { 76 struct adf_kpt_interface_data *user_data; 77 struct adf_accel_dev *accel_dev; 78 79 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 80 if (!accel_dev) 81 return -EINVAL; 82 83 user_data = GET_KPT_USER_DATA(accel_dev); 84 85 return sysfs_emit(buf, "%d\n", user_data->swk_shared); 86 } 87 88 static ssize_t swk_shared_store(struct device *dev, struct device_attribute *attr, 89 const char *buf, size_t count) 90 { 91 struct adf_kpt_interface_data *user_data; 92 struct adf_accel_dev *accel_dev; 93 bool swk_shared; 94 int ret; 95 96 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 97 if (!accel_dev) 98 return -EINVAL; 99 100 if (adf_dev_started(accel_dev)) { 101 dev_info(dev, "Device qat_dev%d must be down before setting swk_shared\n", 102 accel_dev->accel_id); 103 return -EINVAL; 104 } 105 106 ret = kstrtobool(buf, &swk_shared); 107 if (ret) 108 return ret; 109 110 user_data = GET_KPT_USER_DATA(accel_dev); 111 user_data->swk_shared = swk_shared; 112 113 return count; 114 } 115 static DEVICE_ATTR_RW(swk_shared); 116 117 static ssize_t swk_max_ttl_show(struct device *dev, struct device_attribute *attr, 118 char *buf) 119 { 120 struct adf_kpt_interface_data *user_data; 121 struct adf_accel_dev *accel_dev; 122 123 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 124 if (!accel_dev) 125 return -EINVAL; 126 127 user_data = GET_KPT_USER_DATA(accel_dev); 128 129 return sysfs_emit(buf, "%u\n", user_data->swk_max_ttl); 130 } 131 132 static ssize_t swk_max_ttl_store(struct device *dev, struct device_attribute *attr, 133 const char *buf, size_t count) 134 { 135 struct adf_kpt_hw_data *kpt_data; 136 struct adf_accel_dev *accel_dev; 137 unsigned int swk_max_ttl; 138 int ret; 139 140 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 141 if (!accel_dev) 142 return -EINVAL; 143 144 if (adf_dev_started(accel_dev)) { 145 dev_info(dev, "Device qat_dev%d must be down before setting swk_max_ttl\n", 146 accel_dev->accel_id); 147 return -EINVAL; 148 } 149 150 ret = kstrtouint(buf, 10, &swk_max_ttl); 151 if (ret) 152 return ret; 153 154 kpt_data = GET_KPT_CFG_DATA(accel_dev); 155 156 if (swk_max_ttl > kpt_data->max_swk_ttl) { 157 dev_info(dev, "Configuration value is out of range (%u - %u)\n", 158 0, kpt_data->max_swk_ttl); 159 return -EINVAL; 160 } 161 162 kpt_data->user_input.swk_max_ttl = swk_max_ttl; 163 164 return count; 165 } 166 static DEVICE_ATTR_RW(swk_max_ttl); 167 168 static ssize_t swk_cnt_per_fn_show(struct device *dev, struct device_attribute *attr, 169 char *buf) 170 { 171 struct adf_kpt_interface_data *user_data; 172 struct adf_accel_dev *accel_dev; 173 174 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 175 if (!accel_dev) 176 return -EINVAL; 177 178 user_data = GET_KPT_USER_DATA(accel_dev); 179 180 return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_fn); 181 } 182 183 static ssize_t swk_cnt_per_fn_store(struct device *dev, struct device_attribute *attr, 184 const char *buf, size_t count) 185 { 186 struct adf_kpt_hw_data *kpt_data; 187 struct adf_accel_dev *accel_dev; 188 unsigned int swk_cnt_per_fn; 189 int ret; 190 191 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 192 if (!accel_dev) 193 return -EINVAL; 194 195 if (adf_dev_started(accel_dev)) { 196 dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_fn\n", 197 accel_dev->accel_id); 198 return -EINVAL; 199 } 200 201 ret = kstrtouint(buf, 10, &swk_cnt_per_fn); 202 if (ret) 203 return ret; 204 205 kpt_data = GET_KPT_CFG_DATA(accel_dev); 206 207 if (swk_cnt_per_fn > kpt_data->max_swk_cnt_per_fn_pasid) { 208 dev_info(dev, "swk_cnt_per_fn: value out of range (0 - %u)\n", 209 kpt_data->max_swk_cnt_per_fn_pasid); 210 return -EINVAL; 211 } 212 213 kpt_data->user_input.swk_cnt_per_fn = swk_cnt_per_fn; 214 215 return count; 216 } 217 static DEVICE_ATTR_RW(swk_cnt_per_fn); 218 219 static ssize_t swk_cnt_per_pasid_show(struct device *dev, struct device_attribute *attr, 220 char *buf) 221 { 222 struct adf_kpt_interface_data *user_data; 223 struct adf_accel_dev *accel_dev; 224 225 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 226 if (!accel_dev) 227 return -EINVAL; 228 229 user_data = GET_KPT_USER_DATA(accel_dev); 230 231 return sysfs_emit(buf, "%u\n", user_data->swk_cnt_per_pasid); 232 } 233 234 static ssize_t swk_cnt_per_pasid_store(struct device *dev, struct device_attribute *attr, 235 const char *buf, size_t count) 236 { 237 struct adf_kpt_hw_data *kpt_data; 238 struct adf_accel_dev *accel_dev; 239 unsigned int swk_cnt_per_pasid; 240 int ret; 241 242 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 243 if (!accel_dev) 244 return -EINVAL; 245 246 if (adf_dev_started(accel_dev)) { 247 dev_info(dev, "Device qat_dev%d must be down before setting swk_cnt_per_pasid\n", 248 accel_dev->accel_id); 249 return -EINVAL; 250 } 251 252 ret = kstrtouint(buf, 10, &swk_cnt_per_pasid); 253 if (ret) 254 return ret; 255 256 kpt_data = GET_KPT_CFG_DATA(accel_dev); 257 258 if (swk_cnt_per_pasid > kpt_data->max_swk_cnt_per_fn_pasid) { 259 dev_info(dev, "swk_cnt_per_pasid: value out of range (0 - %u)\n", 260 kpt_data->max_swk_cnt_per_fn_pasid); 261 return -EINVAL; 262 } 263 264 kpt_data->user_input.swk_cnt_per_pasid = swk_cnt_per_pasid; 265 266 return count; 267 } 268 static DEVICE_ATTR_RW(swk_cnt_per_pasid); 269 270 static struct attribute *qat_kpt_attrs[] = { 271 &dev_attr_enable.attr, 272 &dev_attr_swk_shared.attr, 273 &dev_attr_swk_max_ttl.attr, 274 &dev_attr_swk_cnt_per_fn.attr, 275 &dev_attr_swk_cnt_per_pasid.attr, 276 NULL, 277 }; 278 279 static const struct attribute_group qat_kpt_group = { 280 .attrs = qat_kpt_attrs, 281 .name = "qat_kpt", 282 }; 283 284 int adf_sysfs_init_kpt(struct adf_accel_dev *accel_dev) 285 { 286 int ret; 287 288 ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_kpt_group); 289 if (ret) { 290 dev_err(&GET_DEV(accel_dev), "Failed to create qat_kpt attribute group\n"); 291 return ret; 292 } 293 294 return 0; 295 } 296 EXPORT_SYMBOL_GPL(adf_sysfs_init_kpt); 297