mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
395 lines
9.6 KiB
C
395 lines
9.6 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/* Copyright(c) 2007-2022 Intel Corporation */
|
|
#include "adf_cfg_bundle.h"
|
|
#include "adf_cfg_strings.h"
|
|
#include "adf_cfg_instance.h"
|
|
#include <sys/cpuset.h>
|
|
|
|
static bool
|
|
adf_cfg_is_interrupt_mode(struct adf_cfg_bundle *bundle)
|
|
{
|
|
return (bundle->polling_mode == ADF_CFG_RESP_EPOLL) ||
|
|
(bundle->type == KERNEL &&
|
|
(bundle->polling_mode != ADF_CFG_RESP_POLL));
|
|
}
|
|
|
|
static bool
|
|
adf_cfg_can_be_shared(struct adf_cfg_bundle *bundle,
|
|
const char *process_name,
|
|
int polling_mode)
|
|
{
|
|
if (adf_cfg_is_free(bundle))
|
|
return true;
|
|
|
|
if (bundle->polling_mode != polling_mode)
|
|
return false;
|
|
|
|
return !adf_cfg_is_interrupt_mode(bundle) ||
|
|
!strncmp(process_name,
|
|
bundle->sections[0],
|
|
ADF_CFG_MAX_SECTION_LEN_IN_BYTES);
|
|
}
|
|
|
|
bool
|
|
adf_cfg_is_free(struct adf_cfg_bundle *bundle)
|
|
{
|
|
return bundle->type == FREE;
|
|
}
|
|
|
|
struct adf_cfg_instance *
|
|
adf_cfg_get_free_instance(struct adf_cfg_device *device,
|
|
struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_instance *inst,
|
|
const char *process_name)
|
|
{
|
|
int i = 0;
|
|
struct adf_cfg_instance *ret_instance = NULL;
|
|
|
|
if (adf_cfg_can_be_shared(bundle, process_name, inst->polling_mode)) {
|
|
for (i = 0; i < device->instance_index; i++) {
|
|
/*
|
|
* the selected instance must match two criteria
|
|
* 1) instance is from the bundle
|
|
* 2) instance type is same
|
|
*/
|
|
if (bundle->number == device->instances[i]->bundle &&
|
|
inst->stype == device->instances[i]->stype) {
|
|
ret_instance = device->instances[i];
|
|
break;
|
|
}
|
|
/*
|
|
* no opportunity to match,
|
|
* quit the loop as early as possible
|
|
*/
|
|
if ((bundle->number + 1) ==
|
|
device->instances[i]->bundle)
|
|
break;
|
|
}
|
|
}
|
|
|
|
return ret_instance;
|
|
}
|
|
|
|
int
|
|
adf_cfg_get_ring_pairs_from_bundle(struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_instance *inst,
|
|
const char *process_name,
|
|
struct adf_cfg_instance *bundle_inst)
|
|
{
|
|
if (inst->polling_mode == ADF_CFG_RESP_POLL &&
|
|
adf_cfg_is_interrupt_mode(bundle)) {
|
|
pr_err("Trying to get ring pairs for a non-interrupt");
|
|
pr_err(" bundle from an interrupt bundle\n");
|
|
return EFAULT;
|
|
}
|
|
|
|
if (inst->stype != bundle_inst->stype) {
|
|
pr_err("Got an instance of different type (cy/dc) than the");
|
|
pr_err(" one request\n");
|
|
return EFAULT;
|
|
}
|
|
|
|
if (strcmp(ADF_KERNEL_SEC, process_name) &&
|
|
strcmp(ADF_KERNEL_SAL_SEC, process_name) &&
|
|
inst->polling_mode != ADF_CFG_RESP_EPOLL &&
|
|
inst->polling_mode != ADF_CFG_RESP_POLL) {
|
|
pr_err("User instance %s needs to be configured", inst->name);
|
|
pr_err(" with IsPolled 1 or 2 for poll and epoll mode,");
|
|
pr_err(" respectively\n");
|
|
return EFAULT;
|
|
}
|
|
|
|
strlcpy(bundle->sections[bundle->section_index],
|
|
process_name,
|
|
ADF_CFG_MAX_STR_LEN);
|
|
bundle->section_index++;
|
|
|
|
if (adf_cfg_is_free(bundle)) {
|
|
bundle->polling_mode = inst->polling_mode;
|
|
bundle->type = (!strcmp(ADF_KERNEL_SEC, process_name) ||
|
|
!strcmp(ADF_KERNEL_SAL_SEC, process_name)) ?
|
|
KERNEL :
|
|
USER;
|
|
if (adf_cfg_is_interrupt_mode(bundle)) {
|
|
CPU_ZERO(&bundle->affinity_mask);
|
|
CPU_COPY(&inst->affinity_mask, &bundle->affinity_mask);
|
|
}
|
|
}
|
|
|
|
switch (inst->stype) {
|
|
case CRYPTO:
|
|
inst->asym_tx = bundle_inst->asym_tx;
|
|
inst->asym_rx = bundle_inst->asym_rx;
|
|
inst->sym_tx = bundle_inst->sym_tx;
|
|
inst->sym_rx = bundle_inst->sym_rx;
|
|
break;
|
|
case COMP:
|
|
inst->dc_tx = bundle_inst->dc_tx;
|
|
inst->dc_rx = bundle_inst->dc_rx;
|
|
break;
|
|
case ASYM:
|
|
inst->asym_tx = bundle_inst->asym_tx;
|
|
inst->asym_rx = bundle_inst->asym_rx;
|
|
break;
|
|
case SYM:
|
|
inst->sym_tx = bundle_inst->sym_tx;
|
|
inst->sym_rx = bundle_inst->sym_rx;
|
|
break;
|
|
default:
|
|
/* unknown service type of instance */
|
|
pr_err("1 Unknown service type %d of instance\n", inst->stype);
|
|
}
|
|
|
|
/* mark it as used */
|
|
bundle_inst->stype = USED;
|
|
|
|
inst->bundle = bundle->number;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
adf_cfg_init_and_insert_inst(struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_device *device,
|
|
int bank_num,
|
|
struct adf_accel_dev *accel_dev)
|
|
{
|
|
struct adf_cfg_instance *cfg_instance = NULL;
|
|
int ring_pair_index = 0;
|
|
int ring_index = 0;
|
|
int i = 0;
|
|
u8 serv_type;
|
|
int num_rings_per_srv = 0;
|
|
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
|
|
u16 ring_to_svc_map = GET_HW_DATA(accel_dev)->ring_to_svc_map;
|
|
|
|
/* init the bundle with instance information */
|
|
for (ring_pair_index = 0; ring_pair_index < bundle->max_cfg_svc_num;
|
|
ring_pair_index++) {
|
|
adf_get_ring_svc_map_data(hw_data,
|
|
bundle->number,
|
|
ring_pair_index,
|
|
&serv_type,
|
|
&ring_index,
|
|
&num_rings_per_srv);
|
|
|
|
for (i = 0; i < num_rings_per_srv; i++) {
|
|
cfg_instance = malloc(sizeof(*cfg_instance),
|
|
M_QAT,
|
|
M_WAITOK | M_ZERO);
|
|
|
|
switch (serv_type) {
|
|
case CRYPTO:
|
|
crypto_instance_init(cfg_instance, bundle);
|
|
break;
|
|
case COMP:
|
|
dc_instance_init(cfg_instance, bundle);
|
|
break;
|
|
case ASYM:
|
|
asym_instance_init(cfg_instance, bundle);
|
|
break;
|
|
case SYM:
|
|
sym_instance_init(cfg_instance, bundle);
|
|
break;
|
|
case NA:
|
|
break;
|
|
|
|
default:
|
|
/* Unknown service type */
|
|
device_printf(
|
|
GET_DEV(accel_dev),
|
|
"Unknown service type %d of instance, mask is 0x%x\n",
|
|
serv_type,
|
|
ring_to_svc_map);
|
|
}
|
|
cfg_instance->bundle = bank_num;
|
|
device->instances[device->instance_index++] =
|
|
cfg_instance;
|
|
cfg_instance = NULL;
|
|
}
|
|
if (serv_type == CRYPTO) {
|
|
ring_pair_index++;
|
|
serv_type =
|
|
GET_SRV_TYPE(ring_to_svc_map, ring_pair_index);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int
|
|
adf_cfg_bundle_init(struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_device *device,
|
|
int bank_num,
|
|
struct adf_accel_dev *accel_dev)
|
|
{
|
|
int i = 0;
|
|
|
|
bundle->number = bank_num;
|
|
/* init ring to service mapping for this bundle */
|
|
adf_cfg_init_ring2serv_mapping(accel_dev, bundle, device);
|
|
|
|
/* init the bundle with instance information */
|
|
adf_cfg_init_and_insert_inst(bundle, device, bank_num, accel_dev);
|
|
|
|
CPU_FILL(&bundle->affinity_mask);
|
|
bundle->type = FREE;
|
|
bundle->polling_mode = -1;
|
|
bundle->section_index = 0;
|
|
|
|
bundle->sections = malloc(sizeof(char *) * bundle->max_section,
|
|
M_QAT,
|
|
M_WAITOK | M_ZERO);
|
|
|
|
for (i = 0; i < bundle->max_section; i++) {
|
|
bundle->sections[i] =
|
|
malloc(ADF_CFG_MAX_STR_LEN, M_QAT, M_WAITOK | M_ZERO);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
adf_cfg_bundle_clear(struct adf_cfg_bundle *bundle,
|
|
struct adf_accel_dev *accel_dev)
|
|
{
|
|
int i = 0;
|
|
|
|
for (i = 0; i < bundle->max_section; i++) {
|
|
if (bundle->sections && bundle->sections[i]) {
|
|
free(bundle->sections[i], M_QAT);
|
|
bundle->sections[i] = NULL;
|
|
}
|
|
}
|
|
|
|
free(bundle->sections, M_QAT);
|
|
bundle->sections = NULL;
|
|
|
|
adf_cfg_rel_ring2serv_mapping(bundle);
|
|
}
|
|
|
|
static void
|
|
adf_cfg_assign_serv_to_rings(struct adf_hw_device_data *hw_data,
|
|
struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_device *device)
|
|
{
|
|
int ring_pair_index = 0;
|
|
int ring_index = 0;
|
|
u8 serv_type = 0;
|
|
int num_req_rings = bundle->num_of_rings / 2;
|
|
int num_rings_per_srv = 0;
|
|
|
|
for (ring_pair_index = 0; ring_pair_index < bundle->max_cfg_svc_num;
|
|
ring_pair_index++) {
|
|
adf_get_ring_svc_map_data(hw_data,
|
|
bundle->number,
|
|
ring_pair_index,
|
|
&serv_type,
|
|
&ring_index,
|
|
&num_rings_per_srv);
|
|
|
|
switch (serv_type) {
|
|
case CRYPTO:
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_ASYM,
|
|
num_rings_per_srv);
|
|
ring_pair_index++;
|
|
ring_index = num_rings_per_srv * ring_pair_index;
|
|
if (ring_pair_index == bundle->max_cfg_svc_num)
|
|
break;
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_SYM,
|
|
num_rings_per_srv);
|
|
break;
|
|
case COMP:
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_DC,
|
|
num_rings_per_srv);
|
|
break;
|
|
case SYM:
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_SYM,
|
|
num_rings_per_srv);
|
|
break;
|
|
case ASYM:
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_ASYM,
|
|
num_rings_per_srv);
|
|
break;
|
|
case NA:
|
|
ASSIGN_SERV_TO_RINGS(bundle,
|
|
ring_index,
|
|
num_req_rings,
|
|
ADF_ACCEL_SERV_NA,
|
|
num_rings_per_srv);
|
|
break;
|
|
|
|
default:
|
|
/* unknown service type */
|
|
pr_err("Unknown service type %d, mask 0x%x.\n",
|
|
serv_type,
|
|
hw_data->ring_to_svc_map);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
adf_cfg_init_ring2serv_mapping(struct adf_accel_dev *accel_dev,
|
|
struct adf_cfg_bundle *bundle,
|
|
struct adf_cfg_device *device)
|
|
{
|
|
struct adf_hw_device_data *hw_data = accel_dev->hw_device;
|
|
struct adf_cfg_ring *ring_in_bundle;
|
|
int ring_num = 0;
|
|
|
|
bundle->num_of_rings = hw_data->num_rings_per_bank;
|
|
if (hw_data->num_rings_per_bank >= (2 * ADF_CFG_NUM_SERVICES))
|
|
bundle->max_cfg_svc_num = ADF_CFG_NUM_SERVICES;
|
|
else
|
|
bundle->max_cfg_svc_num = 1;
|
|
|
|
bundle->rings =
|
|
malloc(bundle->num_of_rings * sizeof(struct adf_cfg_ring *),
|
|
M_QAT,
|
|
M_WAITOK | M_ZERO);
|
|
|
|
for (ring_num = 0; ring_num < bundle->num_of_rings; ring_num++) {
|
|
ring_in_bundle = malloc(sizeof(struct adf_cfg_ring),
|
|
M_QAT,
|
|
M_WAITOK | M_ZERO);
|
|
ring_in_bundle->mode =
|
|
(ring_num < bundle->num_of_rings / 2) ? TX : RX;
|
|
ring_in_bundle->number = ring_num;
|
|
bundle->rings[ring_num] = ring_in_bundle;
|
|
}
|
|
|
|
adf_cfg_assign_serv_to_rings(hw_data, bundle, device);
|
|
|
|
return;
|
|
}
|
|
|
|
int
|
|
adf_cfg_rel_ring2serv_mapping(struct adf_cfg_bundle *bundle)
|
|
{
|
|
int i = 0;
|
|
|
|
if (bundle->rings) {
|
|
for (i = 0; i < bundle->num_of_rings; i++)
|
|
free(bundle->rings[i], M_QAT);
|
|
|
|
free(bundle->rings, M_QAT);
|
|
}
|
|
|
|
return 0;
|
|
}
|