Contributors: 11
Author |
Tokens |
Token Proportion |
Commits |
Commit Proportion |
Małgorzata Mielnik |
482 |
67.98% |
1 |
4.76% |
Giovanni Cabiddu |
74 |
10.44% |
7 |
33.33% |
Tomasz Kowalik |
41 |
5.78% |
1 |
4.76% |
Jie Wang |
36 |
5.08% |
2 |
9.52% |
Tadeusz Struk |
32 |
4.51% |
2 |
9.52% |
Bruce W Allan |
17 |
2.40% |
2 |
9.52% |
Ciunas Bennett |
9 |
1.27% |
1 |
4.76% |
Adam Guerin |
8 |
1.13% |
2 |
9.52% |
Siming Wan |
5 |
0.71% |
1 |
4.76% |
Marco Chiappero |
4 |
0.56% |
1 |
4.76% |
Dan Carpenter |
1 |
0.14% |
1 |
4.76% |
Total |
709 |
|
21 |
|
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright(c) 2023 Intel Corporation */
#include <linux/array_size.h>
#include <linux/bitops.h>
#include <linux/export.h>
#include <linux/pci.h>
#include <linux/string.h>
#include "adf_cfg.h"
#include "adf_cfg_services.h"
#include "adf_cfg_strings.h"
static const char *const adf_cfg_services[] = {
[SVC_ASYM] = ADF_CFG_ASYM,
[SVC_SYM] = ADF_CFG_SYM,
[SVC_DC] = ADF_CFG_DC,
[SVC_DCC] = ADF_CFG_DCC,
};
/*
* Ensure that the size of the array matches the number of services,
* SVC_BASE_COUNT, that is used to size the bitmap.
*/
static_assert(ARRAY_SIZE(adf_cfg_services) == SVC_BASE_COUNT);
/*
* Ensure that the maximum number of concurrent services that can be
* enabled on a device is less than or equal to the number of total
* supported services.
*/
static_assert(ARRAY_SIZE(adf_cfg_services) >= MAX_NUM_CONCURR_SVC);
/*
* Ensure that the number of services fit a single unsigned long, as each
* service is represented by a bit in the mask.
*/
static_assert(BITS_PER_LONG >= SVC_BASE_COUNT);
/*
* Ensure that size of the concatenation of all service strings is smaller
* than the size of the buffer that will contain them.
*/
static_assert(sizeof(ADF_CFG_SYM ADF_SERVICES_DELIMITER
ADF_CFG_ASYM ADF_SERVICES_DELIMITER
ADF_CFG_DC ADF_SERVICES_DELIMITER
ADF_CFG_DCC) < ADF_CFG_MAX_VAL_LEN_IN_BYTES);
static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const char *buf,
size_t len, unsigned long *out_mask)
{
struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
unsigned long mask = 0;
char *substr, *token;
int id, num_svc = 0;
if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1)
return -EINVAL;
strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
substr = services;
while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) {
id = sysfs_match_string(adf_cfg_services, token);
if (id < 0)
return id;
if (test_and_set_bit(id, &mask))
return -EINVAL;
if (num_svc++ == MAX_NUM_CONCURR_SVC)
return -EINVAL;
}
if (hw_data->services_supported && !hw_data->services_supported(mask))
return -EINVAL;
*out_mask = mask;
return 0;
}
static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len)
{
int offset = 0;
int bit;
if (len < ADF_CFG_MAX_VAL_LEN_IN_BYTES)
return -ENOSPC;
for_each_set_bit(bit, &mask, SVC_BASE_COUNT) {
if (offset)
offset += scnprintf(buf + offset, len - offset,
ADF_SERVICES_DELIMITER);
offset += scnprintf(buf + offset, len - offset, "%s",
adf_cfg_services[bit]);
}
return 0;
}
int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in,
size_t in_len, char *out, size_t out_len)
{
unsigned long mask;
int ret;
ret = adf_service_string_to_mask(accel_dev, in, in_len, &mask);
if (ret)
return ret;
if (!mask)
return -EINVAL;
return adf_service_mask_to_string(mask, out, out_len);
}
int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask)
{
char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
size_t len;
int ret;
ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
ADF_SERVICES_ENABLED, services);
if (ret) {
dev_err(&GET_DEV(accel_dev), "%s param not found\n",
ADF_SERVICES_ENABLED);
return ret;
}
len = strnlen(services, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
ret = adf_service_string_to_mask(accel_dev, services, len, mask);
if (ret)
dev_err(&GET_DEV(accel_dev), "Invalid value of %s param: %s\n",
ADF_SERVICES_ENABLED, services);
return ret;
}
EXPORT_SYMBOL_GPL(adf_get_service_mask);
int adf_get_service_enabled(struct adf_accel_dev *accel_dev)
{
unsigned long mask;
int ret;
ret = adf_get_service_mask(accel_dev, &mask);
if (ret)
return ret;
if (test_bit(SVC_SYM, &mask) && test_bit(SVC_ASYM, &mask))
return SVC_SYM_ASYM;
if (test_bit(SVC_SYM, &mask) && test_bit(SVC_DC, &mask))
return SVC_SYM_DC;
if (test_bit(SVC_ASYM, &mask) && test_bit(SVC_DC, &mask))
return SVC_ASYM_DC;
if (test_bit(SVC_SYM, &mask))
return SVC_SYM;
if (test_bit(SVC_ASYM, &mask))
return SVC_ASYM;
if (test_bit(SVC_DC, &mask))
return SVC_DC;
if (test_bit(SVC_DCC, &mask))
return SVC_DCC;
return -EINVAL;
}
EXPORT_SYMBOL_GPL(adf_get_service_enabled);