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