460 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright(c) 2023 Intel Corporation */3 4#define dev_fmt(fmt) "RateLimiting: " fmt5 6#include <linux/dev_printk.h>7#include <linux/pci.h>8#include <linux/sysfs.h>9#include <linux/types.h>10 11#include "adf_common_drv.h"12#include "adf_rl.h"13#include "adf_sysfs_rl.h"14 15#define GET_RL_STRUCT(accel_dev) ((accel_dev)->rate_limiting->user_input)16 17enum rl_ops {18 ADD,19 UPDATE,20 RM,21 RM_ALL,22 GET,23};24 25enum rl_params {26 RP_MASK,27 ID,28 CIR,29 PIR,30 SRV,31 CAP_REM_SRV,32};33 34static const char *const rl_services[] = {35 [ADF_SVC_ASYM] = "asym",36 [ADF_SVC_SYM] = "sym",37 [ADF_SVC_DC] = "dc",38};39 40static const char *const rl_operations[] = {41 [ADD] = "add",42 [UPDATE] = "update",43 [RM] = "rm",44 [RM_ALL] = "rm_all",45 [GET] = "get",46};47 48static int set_param_u(struct device *dev, enum rl_params param, u64 set)49{50 struct adf_rl_interface_data *data;51 struct adf_accel_dev *accel_dev;52 int ret = 0;53 54 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));55 if (!accel_dev)56 return -EINVAL;57 58 data = &GET_RL_STRUCT(accel_dev);59 60 down_write(&data->lock);61 switch (param) {62 case RP_MASK:63 data->input.rp_mask = set;64 break;65 case CIR:66 data->input.cir = set;67 break;68 case PIR:69 data->input.pir = set;70 break;71 case SRV:72 data->input.srv = set;73 break;74 case CAP_REM_SRV:75 data->cap_rem_srv = set;76 break;77 default:78 ret = -EINVAL;79 break;80 }81 up_write(&data->lock);82 83 return ret;84}85 86static int set_param_s(struct device *dev, enum rl_params param, int set)87{88 struct adf_rl_interface_data *data;89 struct adf_accel_dev *accel_dev;90 91 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));92 if (!accel_dev || param != ID)93 return -EINVAL;94 95 data = &GET_RL_STRUCT(accel_dev);96 97 down_write(&data->lock);98 data->input.sla_id = set;99 up_write(&data->lock);100 101 return 0;102}103 104static int get_param_u(struct device *dev, enum rl_params param, u64 *get)105{106 struct adf_rl_interface_data *data;107 struct adf_accel_dev *accel_dev;108 int ret = 0;109 110 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));111 if (!accel_dev)112 return -EINVAL;113 114 data = &GET_RL_STRUCT(accel_dev);115 116 down_read(&data->lock);117 switch (param) {118 case RP_MASK:119 *get = data->input.rp_mask;120 break;121 case CIR:122 *get = data->input.cir;123 break;124 case PIR:125 *get = data->input.pir;126 break;127 case SRV:128 *get = data->input.srv;129 break;130 default:131 ret = -EINVAL;132 }133 up_read(&data->lock);134 135 return ret;136}137 138static int get_param_s(struct device *dev, enum rl_params param)139{140 struct adf_rl_interface_data *data;141 struct adf_accel_dev *accel_dev;142 int ret = 0;143 144 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));145 if (!accel_dev)146 return -EINVAL;147 148 data = &GET_RL_STRUCT(accel_dev);149 150 down_read(&data->lock);151 if (param == ID)152 ret = data->input.sla_id;153 up_read(&data->lock);154 155 return ret;156}157 158static ssize_t rp_show(struct device *dev, struct device_attribute *attr,159 char *buf)160{161 int ret;162 u64 get;163 164 ret = get_param_u(dev, RP_MASK, &get);165 if (ret)166 return ret;167 168 return sysfs_emit(buf, "%#llx\n", get);169}170 171static ssize_t rp_store(struct device *dev, struct device_attribute *attr,172 const char *buf, size_t count)173{174 int err;175 u64 val;176 177 err = kstrtou64(buf, 16, &val);178 if (err)179 return err;180 181 err = set_param_u(dev, RP_MASK, val);182 if (err)183 return err;184 185 return count;186}187static DEVICE_ATTR_RW(rp);188 189static ssize_t id_show(struct device *dev, struct device_attribute *attr,190 char *buf)191{192 return sysfs_emit(buf, "%d\n", get_param_s(dev, ID));193}194 195static ssize_t id_store(struct device *dev, struct device_attribute *attr,196 const char *buf, size_t count)197{198 int err;199 int val;200 201 err = kstrtoint(buf, 10, &val);202 if (err)203 return err;204 205 err = set_param_s(dev, ID, val);206 if (err)207 return err;208 209 return count;210}211static DEVICE_ATTR_RW(id);212 213static ssize_t cir_show(struct device *dev, struct device_attribute *attr,214 char *buf)215{216 int ret;217 u64 get;218 219 ret = get_param_u(dev, CIR, &get);220 if (ret)221 return ret;222 223 return sysfs_emit(buf, "%llu\n", get);224}225 226static ssize_t cir_store(struct device *dev, struct device_attribute *attr,227 const char *buf, size_t count)228{229 unsigned int val;230 int err;231 232 err = kstrtouint(buf, 10, &val);233 if (err)234 return err;235 236 err = set_param_u(dev, CIR, val);237 if (err)238 return err;239 240 return count;241}242static DEVICE_ATTR_RW(cir);243 244static ssize_t pir_show(struct device *dev, struct device_attribute *attr,245 char *buf)246{247 int ret;248 u64 get;249 250 ret = get_param_u(dev, PIR, &get);251 if (ret)252 return ret;253 254 return sysfs_emit(buf, "%llu\n", get);255}256 257static ssize_t pir_store(struct device *dev, struct device_attribute *attr,258 const char *buf, size_t count)259{260 unsigned int val;261 int err;262 263 err = kstrtouint(buf, 10, &val);264 if (err)265 return err;266 267 err = set_param_u(dev, PIR, val);268 if (err)269 return err;270 271 return count;272}273static DEVICE_ATTR_RW(pir);274 275static ssize_t srv_show(struct device *dev, struct device_attribute *attr,276 char *buf)277{278 int ret;279 u64 get;280 281 ret = get_param_u(dev, SRV, &get);282 if (ret)283 return ret;284 285 if (get == ADF_SVC_NONE)286 return -EINVAL;287 288 return sysfs_emit(buf, "%s\n", rl_services[get]);289}290 291static ssize_t srv_store(struct device *dev, struct device_attribute *attr,292 const char *buf, size_t count)293{294 unsigned int val;295 int ret;296 297 ret = sysfs_match_string(rl_services, buf);298 if (ret < 0)299 return ret;300 301 val = ret;302 ret = set_param_u(dev, SRV, val);303 if (ret)304 return ret;305 306 return count;307}308static DEVICE_ATTR_RW(srv);309 310static ssize_t cap_rem_show(struct device *dev, struct device_attribute *attr,311 char *buf)312{313 struct adf_rl_interface_data *data;314 struct adf_accel_dev *accel_dev;315 int ret, rem_cap;316 317 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));318 if (!accel_dev)319 return -EINVAL;320 321 data = &GET_RL_STRUCT(accel_dev);322 323 down_read(&data->lock);324 rem_cap = adf_rl_get_capability_remaining(accel_dev, data->cap_rem_srv,325 RL_SLA_EMPTY_ID);326 up_read(&data->lock);327 if (rem_cap < 0)328 return rem_cap;329 330 ret = sysfs_emit(buf, "%u\n", rem_cap);331 332 return ret;333}334 335static ssize_t cap_rem_store(struct device *dev, struct device_attribute *attr,336 const char *buf, size_t count)337{338 unsigned int val;339 int ret;340 341 ret = sysfs_match_string(rl_services, buf);342 if (ret < 0)343 return ret;344 345 val = ret;346 ret = set_param_u(dev, CAP_REM_SRV, val);347 if (ret)348 return ret;349 350 return count;351}352static DEVICE_ATTR_RW(cap_rem);353 354static ssize_t sla_op_store(struct device *dev, struct device_attribute *attr,355 const char *buf, size_t count)356{357 struct adf_rl_interface_data *data;358 struct adf_accel_dev *accel_dev;359 int ret;360 361 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));362 if (!accel_dev)363 return -EINVAL;364 365 data = &GET_RL_STRUCT(accel_dev);366 367 ret = sysfs_match_string(rl_operations, buf);368 if (ret < 0)369 return ret;370 371 down_write(&data->lock);372 switch (ret) {373 case ADD:374 data->input.parent_id = RL_PARENT_DEFAULT_ID;375 data->input.type = RL_LEAF;376 data->input.sla_id = 0;377 ret = adf_rl_add_sla(accel_dev, &data->input);378 if (ret)379 goto err_free_lock;380 break;381 case UPDATE:382 ret = adf_rl_update_sla(accel_dev, &data->input);383 if (ret)384 goto err_free_lock;385 break;386 case RM:387 ret = adf_rl_remove_sla(accel_dev, data->input.sla_id);388 if (ret)389 goto err_free_lock;390 break;391 case RM_ALL:392 adf_rl_remove_sla_all(accel_dev, false);393 break;394 case GET:395 ret = adf_rl_get_sla(accel_dev, &data->input);396 if (ret)397 goto err_free_lock;398 break;399 default:400 ret = -EINVAL;401 goto err_free_lock;402 }403 up_write(&data->lock);404 405 return count;406 407err_free_lock:408 up_write(&data->lock);409 410 return ret;411}412static DEVICE_ATTR_WO(sla_op);413 414static struct attribute *qat_rl_attrs[] = {415 &dev_attr_rp.attr,416 &dev_attr_id.attr,417 &dev_attr_cir.attr,418 &dev_attr_pir.attr,419 &dev_attr_srv.attr,420 &dev_attr_cap_rem.attr,421 &dev_attr_sla_op.attr,422 NULL,423};424 425static struct attribute_group qat_rl_group = {426 .attrs = qat_rl_attrs,427 .name = "qat_rl",428};429 430int adf_sysfs_rl_add(struct adf_accel_dev *accel_dev)431{432 struct adf_rl_interface_data *data;433 int ret;434 435 data = &GET_RL_STRUCT(accel_dev);436 437 ret = device_add_group(&GET_DEV(accel_dev), &qat_rl_group);438 if (ret)439 dev_err(&GET_DEV(accel_dev),440 "Failed to create qat_rl attribute group\n");441 442 data->cap_rem_srv = ADF_SVC_NONE;443 data->input.srv = ADF_SVC_NONE;444 data->sysfs_added = true;445 446 return ret;447}448 449void adf_sysfs_rl_rm(struct adf_accel_dev *accel_dev)450{451 struct adf_rl_interface_data *data;452 453 data = &GET_RL_STRUCT(accel_dev);454 if (!data->sysfs_added)455 return;456 457 device_remove_group(&GET_DEV(accel_dev), &qat_rl_group);458 data->sysfs_added = false;459}460