File Index
Files and directories
Sign in
FILE

adf_cfg_services.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/intel/qat/qat_common/adf_cfg_services.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright(c) 2023 Intel Corporation */
  3
  4#include <linux/array_size.h>
  5#include <linux/bitops.h>
  6#include <linux/export.h>
  7#include <linux/pci.h>
  8#include <linux/string.h>
  9#include "adf_cfg.h"
 10#include "adf_cfg_common.h"
 11#include "adf_cfg_services.h"
 12#include "adf_cfg_strings.h"
 13
 14static const char *const adf_cfg_services[] = {
 15	[SVC_ASYM] = ADF_CFG_ASYM,
 16	[SVC_SYM] = ADF_CFG_SYM,
 17	[SVC_DC] = ADF_CFG_DC,
 18	[SVC_DCC] = ADF_CFG_DCC,
 19	[SVC_DECOMP] = ADF_CFG_DECOMP,
 20};
 21
 22/*
 23 * Ensure that the size of the array matches the number of services,
 24 * SVC_COUNT, that is used to size the bitmap.
 25 */
 26static_assert(ARRAY_SIZE(adf_cfg_services) == SVC_COUNT);
 27
 28/*
 29 * Ensure that the maximum number of concurrent services that can be
 30 * enabled on a device is less than or equal to the number of total
 31 * supported services.
 32 */
 33static_assert(ARRAY_SIZE(adf_cfg_services) >= MAX_NUM_CONCURR_SVC);
 34
 35/*
 36 * Ensure that the number of services fit a single unsigned long, as each
 37 * service is represented by a bit in the mask.
 38 */
 39static_assert(BITS_PER_LONG >= SVC_COUNT);
 40
 41/*
 42 * Ensure that size of the concatenation of all service strings is smaller
 43 * than the size of the buffer that will contain them.
 44 */
 45static_assert(sizeof(ADF_CFG_SYM ADF_SERVICES_DELIMITER
 46		     ADF_CFG_ASYM ADF_SERVICES_DELIMITER
 47		     ADF_CFG_DC ADF_SERVICES_DELIMITER
 48		     ADF_CFG_DECOMP ADF_SERVICES_DELIMITER
 49		     ADF_CFG_DCC) < ADF_CFG_MAX_VAL_LEN_IN_BYTES);
 50
 51static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const char *buf,
 52				      size_t len, unsigned long *out_mask)
 53{
 54	struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
 55	char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
 56	unsigned long mask = 0;
 57	char *substr, *token;
 58	int id, num_svc = 0;
 59
 60	if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1)
 61		return -EINVAL;
 62
 63	strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
 64	substr = services;
 65
 66	while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) {
 67		id = sysfs_match_string(adf_cfg_services, token);
 68		if (id < 0)
 69			return id;
 70
 71		if (test_and_set_bit(id, &mask))
 72			return -EINVAL;
 73
 74		if (num_svc++ == MAX_NUM_CONCURR_SVC)
 75			return -EINVAL;
 76	}
 77
 78	if (hw_data->services_supported && !hw_data->services_supported(mask))
 79		return -EINVAL;
 80
 81	*out_mask = mask;
 82
 83	return 0;
 84}
 85
 86static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len)
 87{
 88	int offset = 0;
 89	int bit;
 90
 91	if (len < ADF_CFG_MAX_VAL_LEN_IN_BYTES)
 92		return -ENOSPC;
 93
 94	for_each_set_bit(bit, &mask, SVC_COUNT) {
 95		if (offset)
 96			offset += scnprintf(buf + offset, len - offset,
 97					    ADF_SERVICES_DELIMITER);
 98
 99		offset += scnprintf(buf + offset, len - offset, "%s",
100				    adf_cfg_services[bit]);
101	}
102
103	return 0;
104}
105
106int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in,
107			     size_t in_len, char *out, size_t out_len)
108{
109	unsigned long mask;
110	int ret;
111
112	ret = adf_service_string_to_mask(accel_dev, in, in_len, &mask);
113	if (ret)
114		return ret;
115
116	if (!mask)
117		return -EINVAL;
118
119	return adf_service_mask_to_string(mask, out, out_len);
120}
121
122int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask)
123{
124	char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
125	size_t len;
126	int ret;
127
128	ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
129				      ADF_SERVICES_ENABLED, services);
130	if (ret) {
131		dev_err(&GET_DEV(accel_dev), "%s param not found\n",
132			ADF_SERVICES_ENABLED);
133		return ret;
134	}
135
136	len = strnlen(services, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
137	ret = adf_service_string_to_mask(accel_dev, services, len, mask);
138	if (ret)
139		dev_err(&GET_DEV(accel_dev), "Invalid value of %s param: %s\n",
140			ADF_SERVICES_ENABLED, services);
141
142	return ret;
143}
144EXPORT_SYMBOL_GPL(adf_get_service_mask);
145
146int adf_get_service_enabled(struct adf_accel_dev *accel_dev)
147{
148	unsigned long mask;
149	int ret;
150
151	ret = adf_get_service_mask(accel_dev, &mask);
152	if (ret)
153		return ret;
154
155	if (test_bit(SVC_SYM, &mask) && test_bit(SVC_ASYM, &mask))
156		return SVC_SYM_ASYM;
157
158	if (test_bit(SVC_SYM, &mask) && test_bit(SVC_DC, &mask))
159		return SVC_SYM_DC;
160
161	if (test_bit(SVC_ASYM, &mask) && test_bit(SVC_DC, &mask))
162		return SVC_ASYM_DC;
163
164	if (test_bit(SVC_SYM, &mask))
165		return SVC_SYM;
166
167	if (test_bit(SVC_ASYM, &mask))
168		return SVC_ASYM;
169
170	if (test_bit(SVC_DC, &mask))
171		return SVC_DC;
172
173	if (test_bit(SVC_DECOMP, &mask))
174		return SVC_DECOMP;
175
176	if (test_bit(SVC_DCC, &mask))
177		return SVC_DCC;
178
179	return -EINVAL;
180}
181EXPORT_SYMBOL_GPL(adf_get_service_enabled);
182
183enum adf_cfg_service_type adf_srv_to_cfg_svc_type(enum adf_base_services svc)
184{
185	switch (svc) {
186	case SVC_ASYM:
187		return ASYM;
188	case SVC_SYM:
189		return SYM;
190	case SVC_DC:
191		return COMP;
192	case SVC_DECOMP:
193		return DECOMP;
194	default:
195		return UNUSED;
196	}
197}
198
199bool adf_is_service_enabled(struct adf_accel_dev *accel_dev, enum adf_base_services svc)
200{
201	enum adf_cfg_service_type arb_srv = adf_srv_to_cfg_svc_type(svc);
202	struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
203	u8 rps_per_bundle = hw_data->num_banks_per_vf;
204	int i;
205
206	for (i = 0; i < rps_per_bundle; i++) {
207		if (GET_SRV_TYPE(accel_dev, i) == arb_srv)
208			return true;
209	}
210
211	return false;
212}
~/ Read-only file preview.