1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 /* $FreeBSD$ */ 4 #include <sys/types.h> 5 #include <sys/sysctl.h> 6 #include <sys/systm.h> 7 #include "adf_accel_devices.h" 8 #include "adf_cfg.h" 9 #include "adf_cfg_sysctl.h" 10 #include "adf_cfg_device.h" 11 #include "adf_common_drv.h" 12 #include <sys/mutex.h> 13 #include <sys/sbuf.h> 14 15 #define ADF_CFG_SYSCTL_BUF_SZ ADF_CFG_MAX_VAL 16 #define ADF_CFG_UP_STR "up" 17 #define ADF_CFG_DOWN_STR "down" 18 19 #define ADF_CFG_MAX_USER_PROCESSES 64 20 21 static int 22 adf_cfg_down(struct adf_accel_dev *accel_dev) 23 { 24 int ret = 0; 25 26 if (!adf_dev_started(accel_dev)) { 27 device_printf(GET_DEV(accel_dev), 28 "Device qat_dev%d already down\n", 29 accel_dev->accel_id); 30 return 0; 31 } 32 33 if (adf_dev_in_use(accel_dev)) { 34 pr_err("QAT: Device %d in use\n", accel_dev->accel_id); 35 goto out; 36 } 37 38 if (adf_dev_stop(accel_dev)) { 39 device_printf(GET_DEV(accel_dev), 40 "Failed to stop qat_dev%d\n", 41 accel_dev->accel_id); 42 ret = EFAULT; 43 goto out; 44 } 45 46 adf_dev_shutdown(accel_dev); 47 48 out: 49 return ret; 50 } 51 52 static int 53 adf_cfg_up(struct adf_accel_dev *accel_dev) 54 { 55 int ret; 56 57 if (adf_dev_started(accel_dev)) 58 return 0; 59 60 if (NULL == accel_dev->hw_device->config_device) 61 return ENXIO; 62 63 ret = accel_dev->hw_device->config_device(accel_dev); 64 if (ret) { 65 device_printf(GET_DEV(accel_dev), 66 "Failed to start qat_dev%d\n", 67 accel_dev->accel_id); 68 return ret; 69 } 70 71 ret = adf_dev_init(accel_dev); 72 if (!ret) 73 ret = adf_dev_start(accel_dev); 74 75 if (ret) { 76 device_printf(GET_DEV(accel_dev), 77 "Failed to start qat_dev%d\n", 78 accel_dev->accel_id); 79 adf_dev_stop(accel_dev); 80 adf_dev_shutdown(accel_dev); 81 } 82 83 if (!ret) { 84 struct adf_cfg_device *cfg_dev = NULL; 85 86 cfg_dev = accel_dev->cfg->dev; 87 adf_cfg_device_clear(cfg_dev, accel_dev); 88 free(cfg_dev, M_QAT); 89 accel_dev->cfg->dev = NULL; 90 } 91 92 return 0; 93 } 94 95 static const char *const cfg_serv[] = 96 { "sym;asym", "sym", "asym", "dc", "sym;dc", "asym;dc", "cy", "cy;dc" }; 97 98 static const char *const cfg_mode[] = { "ks;us", "us", "ks" }; 99 100 static int adf_cfg_sysctl_services_handle(SYSCTL_HANDLER_ARGS) 101 { 102 struct adf_cfg_device_data *dev_cfg_data; 103 struct adf_accel_dev *accel_dev; 104 char buf[ADF_CFG_SYSCTL_BUF_SZ]; 105 unsigned int len; 106 int ret = 0; 107 int i = 0; 108 109 accel_dev = arg1; 110 if (!accel_dev) 111 return ENXIO; 112 113 dev_cfg_data = accel_dev->cfg; 114 if (!dev_cfg_data) 115 return ENXIO; 116 117 strlcpy(buf, dev_cfg_data->cfg_services, sizeof(buf)); 118 119 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req); 120 if (ret != 0 || req->newptr == NULL) 121 return ret; 122 123 /* Handle config change */ 124 if (adf_dev_started(accel_dev)) { 125 device_printf( 126 GET_DEV(accel_dev), 127 "QAT: configuration could be changed in down state only\n"); 128 return EINVAL; 129 } 130 131 len = strlen(buf); 132 133 for (i = 0; i < ARRAY_SIZE(cfg_serv); i++) { 134 if ((len > 0 && strncasecmp(cfg_serv[i], buf, len) == 0)) { 135 strlcpy(dev_cfg_data->cfg_services, 136 buf, 137 ADF_CFG_MAX_VAL); 138 break; 139 } 140 } 141 142 if (i == ARRAY_SIZE(cfg_serv)) { 143 device_printf(GET_DEV(accel_dev), 144 "Unknown service configuration\n"); 145 ret = EINVAL; 146 } 147 148 return ret; 149 } 150 151 static int adf_cfg_sysctl_mode_handle(SYSCTL_HANDLER_ARGS) 152 { 153 struct adf_cfg_device_data *dev_cfg_data; 154 struct adf_accel_dev *accel_dev; 155 char buf[ADF_CFG_SYSCTL_BUF_SZ]; 156 unsigned int len; 157 int ret = 0; 158 int i = 0; 159 160 accel_dev = arg1; 161 if (!accel_dev) 162 return ENXIO; 163 164 dev_cfg_data = accel_dev->cfg; 165 if (!dev_cfg_data) 166 return ENXIO; 167 168 strlcpy(buf, dev_cfg_data->cfg_mode, sizeof(buf)); 169 170 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req); 171 if (ret != 0 || req->newptr == NULL) 172 return ret; 173 174 /* Handle config change */ 175 if (adf_dev_started(accel_dev)) { 176 device_printf( 177 GET_DEV(accel_dev), 178 "QAT: configuration could be changed in down state only\n"); 179 return EBUSY; 180 } 181 182 len = strlen(buf); 183 184 for (i = 0; i < ARRAY_SIZE(cfg_mode); i++) { 185 if ((len > 0 && strncasecmp(cfg_mode[i], buf, len) == 0)) { 186 strlcpy(dev_cfg_data->cfg_mode, buf, ADF_CFG_MAX_VAL); 187 break; 188 } 189 } 190 191 if (i == ARRAY_SIZE(cfg_mode)) { 192 device_printf(GET_DEV(accel_dev), 193 "Unknown configuration mode\n"); 194 ret = EINVAL; 195 } 196 197 return ret; 198 } 199 200 static int adf_cfg_sysctl_handle(SYSCTL_HANDLER_ARGS) 201 { 202 struct adf_cfg_device_data *dev_cfg_data; 203 struct adf_accel_dev *accel_dev; 204 char buf[ADF_CFG_SYSCTL_BUF_SZ] = { 0 }; 205 unsigned int len; 206 int ret = 0; 207 208 accel_dev = arg1; 209 if (!accel_dev) 210 return ENXIO; 211 212 dev_cfg_data = accel_dev->cfg; 213 if (!dev_cfg_data) 214 return ENXIO; 215 216 if (adf_dev_started(accel_dev)) { 217 strlcpy(buf, ADF_CFG_UP_STR, sizeof(buf)); 218 } else { 219 strlcpy(buf, ADF_CFG_DOWN_STR, sizeof(buf)); 220 } 221 222 ret = sysctl_handle_string(oidp, buf, sizeof(buf), req); 223 if (ret != 0 || req->newptr == NULL) 224 return ret; 225 226 len = strlen(buf); 227 228 if ((len > 0 && strncasecmp(ADF_CFG_UP_STR, buf, len) == 0)) { 229 ret = adf_cfg_up(accel_dev); 230 231 } else if (len > 0 && strncasecmp(ADF_CFG_DOWN_STR, buf, len) == 0) { 232 ret = adf_cfg_down(accel_dev); 233 234 } else { 235 device_printf(GET_DEV(accel_dev), "QAT: Invalid operation\n"); 236 ret = EINVAL; 237 } 238 239 return ret; 240 } 241 242 static int adf_cfg_sysctl_num_processes_handle(SYSCTL_HANDLER_ARGS) 243 { 244 struct adf_cfg_device_data *dev_cfg_data; 245 struct adf_accel_dev *accel_dev; 246 uint32_t num_user_processes = 0; 247 int ret = 0; 248 249 accel_dev = arg1; 250 if (!accel_dev) 251 return ENXIO; 252 253 dev_cfg_data = accel_dev->cfg; 254 if (!dev_cfg_data) 255 return ENXIO; 256 257 num_user_processes = dev_cfg_data->num_user_processes; 258 259 ret = sysctl_handle_int(oidp, &num_user_processes, 0, req); 260 if (ret != 0 || req->newptr == NULL) 261 return ret; 262 263 if (adf_dev_started(accel_dev)) { 264 device_printf( 265 GET_DEV(accel_dev), 266 "QAT: configuration could be changed in down state only\n"); 267 return EBUSY; 268 } 269 270 if (num_user_processes > ADF_CFG_MAX_USER_PROCESSES) { 271 return EINVAL; 272 } 273 274 dev_cfg_data->num_user_processes = num_user_processes; 275 276 return ret; 277 } 278 279 int 280 adf_cfg_sysctl_add(struct adf_accel_dev *accel_dev) 281 { 282 struct sysctl_ctx_list *qat_sysctl_ctx; 283 struct sysctl_oid *qat_sysctl_tree; 284 285 if (!accel_dev) 286 return EINVAL; 287 288 qat_sysctl_ctx = 289 device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); 290 qat_sysctl_tree = 291 device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); 292 293 SYSCTL_ADD_PROC(qat_sysctl_ctx, 294 SYSCTL_CHILDREN(qat_sysctl_tree), 295 OID_AUTO, 296 "state", 297 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 298 accel_dev, 299 0, 300 adf_cfg_sysctl_handle, 301 "A", 302 "QAT State"); 303 304 SYSCTL_ADD_PROC(qat_sysctl_ctx, 305 SYSCTL_CHILDREN(qat_sysctl_tree), 306 OID_AUTO, 307 "cfg_services", 308 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 309 accel_dev, 310 0, 311 adf_cfg_sysctl_services_handle, 312 "A", 313 "QAT services confguration"); 314 315 SYSCTL_ADD_PROC(qat_sysctl_ctx, 316 SYSCTL_CHILDREN(qat_sysctl_tree), 317 OID_AUTO, 318 "cfg_mode", 319 CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 320 accel_dev, 321 0, 322 adf_cfg_sysctl_mode_handle, 323 "A", 324 "QAT mode configuration"); 325 326 SYSCTL_ADD_PROC(qat_sysctl_ctx, 327 SYSCTL_CHILDREN(qat_sysctl_tree), 328 OID_AUTO, 329 "num_user_processes", 330 CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 331 accel_dev, 332 0, 333 adf_cfg_sysctl_num_processes_handle, 334 "I", 335 "QAT user processes number "); 336 337 return 0; 338 } 339 340 void 341 adf_cfg_sysctl_remove(struct adf_accel_dev *accel_dev) 342 { 343 } 344