mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
342 lines
7.1 KiB
C
342 lines
7.1 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/* Copyright(c) 2007-2022 Intel Corporation */
|
|
#include <sys/types.h>
|
|
#include <sys/sysctl.h>
|
|
#include <sys/systm.h>
|
|
#include "adf_accel_devices.h"
|
|
#include "adf_cfg.h"
|
|
#include "adf_cfg_sysctl.h"
|
|
#include "adf_cfg_device.h"
|
|
#include "adf_common_drv.h"
|
|
#include <sys/mutex.h>
|
|
#include <sys/sbuf.h>
|
|
|
|
#define ADF_CFG_SYSCTL_BUF_SZ ADF_CFG_MAX_VAL
|
|
#define ADF_CFG_UP_STR "up"
|
|
#define ADF_CFG_DOWN_STR "down"
|
|
|
|
#define ADF_CFG_MAX_USER_PROCESSES 64
|
|
|
|
static int
|
|
adf_cfg_down(struct adf_accel_dev *accel_dev)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (!adf_dev_started(accel_dev)) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Device qat_dev%d already down\n",
|
|
accel_dev->accel_id);
|
|
return 0;
|
|
}
|
|
|
|
if (adf_dev_in_use(accel_dev)) {
|
|
pr_err("QAT: Device %d in use\n", accel_dev->accel_id);
|
|
goto out;
|
|
}
|
|
|
|
if (adf_dev_stop(accel_dev)) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Failed to stop qat_dev%d\n",
|
|
accel_dev->accel_id);
|
|
ret = EFAULT;
|
|
goto out;
|
|
}
|
|
|
|
adf_dev_shutdown(accel_dev);
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static int
|
|
adf_cfg_up(struct adf_accel_dev *accel_dev)
|
|
{
|
|
int ret;
|
|
|
|
if (adf_dev_started(accel_dev))
|
|
return 0;
|
|
|
|
if (NULL == accel_dev->hw_device->config_device)
|
|
return ENXIO;
|
|
|
|
ret = accel_dev->hw_device->config_device(accel_dev);
|
|
if (ret) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Failed to start qat_dev%d\n",
|
|
accel_dev->accel_id);
|
|
return ret;
|
|
}
|
|
|
|
ret = adf_dev_init(accel_dev);
|
|
if (!ret)
|
|
ret = adf_dev_start(accel_dev);
|
|
|
|
if (ret) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Failed to start qat_dev%d\n",
|
|
accel_dev->accel_id);
|
|
adf_dev_stop(accel_dev);
|
|
adf_dev_shutdown(accel_dev);
|
|
}
|
|
|
|
if (!ret) {
|
|
struct adf_cfg_device *cfg_dev = NULL;
|
|
|
|
cfg_dev = accel_dev->cfg->dev;
|
|
adf_cfg_device_clear(cfg_dev, accel_dev);
|
|
free(cfg_dev, M_QAT);
|
|
accel_dev->cfg->dev = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const char *const cfg_serv[] =
|
|
{ "sym;asym", "sym", "asym", "dc", "sym;dc", "asym;dc", "cy", "cy;dc" };
|
|
|
|
static const char *const cfg_mode[] = { "ks;us", "us", "ks" };
|
|
|
|
static int adf_cfg_sysctl_services_handle(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct adf_cfg_device_data *dev_cfg_data;
|
|
struct adf_accel_dev *accel_dev;
|
|
char buf[ADF_CFG_SYSCTL_BUF_SZ];
|
|
unsigned int len;
|
|
int ret = 0;
|
|
int i = 0;
|
|
|
|
accel_dev = arg1;
|
|
if (!accel_dev)
|
|
return ENXIO;
|
|
|
|
dev_cfg_data = accel_dev->cfg;
|
|
if (!dev_cfg_data)
|
|
return ENXIO;
|
|
|
|
strlcpy(buf, dev_cfg_data->cfg_services, sizeof(buf));
|
|
|
|
ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
if (ret != 0 || req->newptr == NULL)
|
|
return ret;
|
|
|
|
/* Handle config change */
|
|
if (adf_dev_started(accel_dev)) {
|
|
device_printf(
|
|
GET_DEV(accel_dev),
|
|
"QAT: configuration could be changed in down state only\n");
|
|
return EINVAL;
|
|
}
|
|
|
|
len = strlen(buf);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(cfg_serv); i++) {
|
|
if ((len > 0 && strncasecmp(cfg_serv[i], buf, len) == 0)) {
|
|
strlcpy(dev_cfg_data->cfg_services,
|
|
buf,
|
|
ADF_CFG_MAX_VAL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == ARRAY_SIZE(cfg_serv)) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Unknown service configuration\n");
|
|
ret = EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int adf_cfg_sysctl_mode_handle(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct adf_cfg_device_data *dev_cfg_data;
|
|
struct adf_accel_dev *accel_dev;
|
|
char buf[ADF_CFG_SYSCTL_BUF_SZ];
|
|
unsigned int len;
|
|
int ret = 0;
|
|
int i = 0;
|
|
|
|
accel_dev = arg1;
|
|
if (!accel_dev)
|
|
return ENXIO;
|
|
|
|
dev_cfg_data = accel_dev->cfg;
|
|
if (!dev_cfg_data)
|
|
return ENXIO;
|
|
|
|
strlcpy(buf, dev_cfg_data->cfg_mode, sizeof(buf));
|
|
|
|
ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
if (ret != 0 || req->newptr == NULL)
|
|
return ret;
|
|
|
|
/* Handle config change */
|
|
if (adf_dev_started(accel_dev)) {
|
|
device_printf(
|
|
GET_DEV(accel_dev),
|
|
"QAT: configuration could be changed in down state only\n");
|
|
return EBUSY;
|
|
}
|
|
|
|
len = strlen(buf);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(cfg_mode); i++) {
|
|
if ((len > 0 && strncasecmp(cfg_mode[i], buf, len) == 0)) {
|
|
strlcpy(dev_cfg_data->cfg_mode, buf, ADF_CFG_MAX_VAL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == ARRAY_SIZE(cfg_mode)) {
|
|
device_printf(GET_DEV(accel_dev),
|
|
"Unknown configuration mode\n");
|
|
ret = EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int adf_cfg_sysctl_handle(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct adf_cfg_device_data *dev_cfg_data;
|
|
struct adf_accel_dev *accel_dev;
|
|
char buf[ADF_CFG_SYSCTL_BUF_SZ] = { 0 };
|
|
unsigned int len;
|
|
int ret = 0;
|
|
|
|
accel_dev = arg1;
|
|
if (!accel_dev)
|
|
return ENXIO;
|
|
|
|
dev_cfg_data = accel_dev->cfg;
|
|
if (!dev_cfg_data)
|
|
return ENXIO;
|
|
|
|
if (adf_dev_started(accel_dev)) {
|
|
strlcpy(buf, ADF_CFG_UP_STR, sizeof(buf));
|
|
} else {
|
|
strlcpy(buf, ADF_CFG_DOWN_STR, sizeof(buf));
|
|
}
|
|
|
|
ret = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
if (ret != 0 || req->newptr == NULL)
|
|
return ret;
|
|
|
|
len = strlen(buf);
|
|
|
|
if ((len > 0 && strncasecmp(ADF_CFG_UP_STR, buf, len) == 0)) {
|
|
ret = adf_cfg_up(accel_dev);
|
|
|
|
} else if (len > 0 && strncasecmp(ADF_CFG_DOWN_STR, buf, len) == 0) {
|
|
ret = adf_cfg_down(accel_dev);
|
|
|
|
} else {
|
|
device_printf(GET_DEV(accel_dev), "QAT: Invalid operation\n");
|
|
ret = EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int adf_cfg_sysctl_num_processes_handle(SYSCTL_HANDLER_ARGS)
|
|
{
|
|
struct adf_cfg_device_data *dev_cfg_data;
|
|
struct adf_accel_dev *accel_dev;
|
|
uint32_t num_user_processes = 0;
|
|
int ret = 0;
|
|
|
|
accel_dev = arg1;
|
|
if (!accel_dev)
|
|
return ENXIO;
|
|
|
|
dev_cfg_data = accel_dev->cfg;
|
|
if (!dev_cfg_data)
|
|
return ENXIO;
|
|
|
|
num_user_processes = dev_cfg_data->num_user_processes;
|
|
|
|
ret = sysctl_handle_int(oidp, &num_user_processes, 0, req);
|
|
if (ret != 0 || req->newptr == NULL)
|
|
return ret;
|
|
|
|
if (adf_dev_started(accel_dev)) {
|
|
device_printf(
|
|
GET_DEV(accel_dev),
|
|
"QAT: configuration could be changed in down state only\n");
|
|
return EBUSY;
|
|
}
|
|
|
|
if (num_user_processes > ADF_CFG_MAX_USER_PROCESSES) {
|
|
return EINVAL;
|
|
}
|
|
|
|
dev_cfg_data->num_user_processes = num_user_processes;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
adf_cfg_sysctl_add(struct adf_accel_dev *accel_dev)
|
|
{
|
|
struct sysctl_ctx_list *qat_sysctl_ctx;
|
|
struct sysctl_oid *qat_sysctl_tree;
|
|
|
|
if (!accel_dev)
|
|
return EINVAL;
|
|
|
|
qat_sysctl_ctx =
|
|
device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
|
|
qat_sysctl_tree =
|
|
device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
|
|
|
|
SYSCTL_ADD_PROC(qat_sysctl_ctx,
|
|
SYSCTL_CHILDREN(qat_sysctl_tree),
|
|
OID_AUTO,
|
|
"state",
|
|
CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
|
|
accel_dev,
|
|
0,
|
|
adf_cfg_sysctl_handle,
|
|
"A",
|
|
"QAT State");
|
|
|
|
SYSCTL_ADD_PROC(qat_sysctl_ctx,
|
|
SYSCTL_CHILDREN(qat_sysctl_tree),
|
|
OID_AUTO,
|
|
"cfg_services",
|
|
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
|
|
accel_dev,
|
|
0,
|
|
adf_cfg_sysctl_services_handle,
|
|
"A",
|
|
"QAT services confguration");
|
|
|
|
SYSCTL_ADD_PROC(qat_sysctl_ctx,
|
|
SYSCTL_CHILDREN(qat_sysctl_tree),
|
|
OID_AUTO,
|
|
"cfg_mode",
|
|
CTLTYPE_STRING | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
|
|
accel_dev,
|
|
0,
|
|
adf_cfg_sysctl_mode_handle,
|
|
"A",
|
|
"QAT mode configuration");
|
|
|
|
SYSCTL_ADD_PROC(qat_sysctl_ctx,
|
|
SYSCTL_CHILDREN(qat_sysctl_tree),
|
|
OID_AUTO,
|
|
"num_user_processes",
|
|
CTLTYPE_U32 | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT,
|
|
accel_dev,
|
|
0,
|
|
adf_cfg_sysctl_num_processes_handle,
|
|
"I",
|
|
"QAT user processes number ");
|
|
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
adf_cfg_sysctl_remove(struct adf_accel_dev *accel_dev)
|
|
{
|
|
}
|