Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

crypto: qat - refactor service parsing logic

The service parsing logic is used to parse the configuration string
provided by the user using the attribute qat/cfg_services in sysfs.
The logic relies on hard-coded strings. For example, the service
"sym;asym" is also replicated as "asym;sym".
This makes the addition of new services or service combinations
complex as it requires the addition of new hard-coded strings for all
possible combinations.

This commit addresses this issue by:
* reducing the number of internal service strings to only the basic
service representations.
* modifying the service parsing logic to analyze the service string
token by token instead of comparing a whole string with patterns.
* introducing the concept of a service mask where each service is
represented by a single bit.
* dividing the parsing logic into several functions to allow for code
reuse (e.g. by sysfs-related functions).
* introducing a new, device generation-specific function to verify
whether the requested service combination is supported by the
currently used device.

Signed-off-by: Małgorzata Mielnik <malgorzata.mielnik@intel.com>
Co-developed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Małgorzata Mielnik and committed by
Herbert Xu
5ab6c06d 9057f824

+203 -79
+4 -12
drivers/crypto/intel/qat/qat_420xx/adf_420xx_hw_data.c
··· 106 106 static u32 uof_get_num_objs(struct adf_accel_dev *accel_dev) 107 107 { 108 108 switch (adf_get_service_enabled(accel_dev)) { 109 - case SVC_CY: 110 - case SVC_CY2: 109 + case SVC_SYM_ASYM: 111 110 return ARRAY_SIZE(adf_fw_cy_config); 112 111 case SVC_DC: 113 112 return ARRAY_SIZE(adf_fw_dc_config); ··· 117 118 case SVC_ASYM: 118 119 return ARRAY_SIZE(adf_fw_asym_config); 119 120 case SVC_ASYM_DC: 120 - case SVC_DC_ASYM: 121 121 return ARRAY_SIZE(adf_fw_asym_dc_config); 122 122 case SVC_SYM_DC: 123 - case SVC_DC_SYM: 124 123 return ARRAY_SIZE(adf_fw_sym_dc_config); 125 124 default: 126 125 return 0; ··· 128 131 static const struct adf_fw_config *get_fw_config(struct adf_accel_dev *accel_dev) 129 132 { 130 133 switch (adf_get_service_enabled(accel_dev)) { 131 - case SVC_CY: 132 - case SVC_CY2: 134 + case SVC_SYM_ASYM: 133 135 return adf_fw_cy_config; 134 136 case SVC_DC: 135 137 return adf_fw_dc_config; ··· 139 143 case SVC_ASYM: 140 144 return adf_fw_asym_config; 141 145 case SVC_ASYM_DC: 142 - case SVC_DC_ASYM: 143 146 return adf_fw_asym_dc_config; 144 147 case SVC_SYM_DC: 145 - case SVC_DC_SYM: 146 148 return adf_fw_sym_dc_config; 147 149 default: 148 150 return NULL; ··· 260 266 } 261 267 262 268 switch (adf_get_service_enabled(accel_dev)) { 263 - case SVC_CY: 264 - case SVC_CY2: 269 + case SVC_SYM_ASYM: 265 270 return capabilities_sym | capabilities_asym; 266 271 case SVC_DC: 267 272 return capabilities_dc; ··· 277 284 case SVC_ASYM: 278 285 return capabilities_asym; 279 286 case SVC_ASYM_DC: 280 - case SVC_DC_ASYM: 281 287 return capabilities_asym | capabilities_dc; 282 288 case SVC_SYM_DC: 283 - case SVC_DC_SYM: 284 289 return capabilities_sym | capabilities_dc; 285 290 default: 286 291 return 0; ··· 473 482 hw_data->get_hb_clock = adf_gen4_get_heartbeat_clock; 474 483 hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; 475 484 hw_data->clock_frequency = ADF_420XX_AE_FREQ; 485 + hw_data->services_supported = adf_gen4_services_supported; 476 486 477 487 adf_gen4_set_err_mask(&hw_data->dev_err_mask); 478 488 adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
+3 -8
drivers/crypto/intel/qat/qat_4xxx/adf_4xxx_hw_data.c
··· 178 178 } 179 179 180 180 switch (adf_get_service_enabled(accel_dev)) { 181 - case SVC_CY: 182 - case SVC_CY2: 181 + case SVC_SYM_ASYM: 183 182 return capabilities_sym | capabilities_asym; 184 183 case SVC_DC: 185 184 return capabilities_dc; ··· 195 196 case SVC_ASYM: 196 197 return capabilities_asym; 197 198 case SVC_ASYM_DC: 198 - case SVC_DC_ASYM: 199 199 return capabilities_asym | capabilities_dc; 200 200 case SVC_SYM_DC: 201 - case SVC_DC_SYM: 202 201 return capabilities_sym | capabilities_dc; 203 202 default: 204 203 return 0; ··· 238 241 static const struct adf_fw_config *get_fw_config(struct adf_accel_dev *accel_dev) 239 242 { 240 243 switch (adf_get_service_enabled(accel_dev)) { 241 - case SVC_CY: 242 - case SVC_CY2: 244 + case SVC_SYM_ASYM: 243 245 return adf_fw_cy_config; 244 246 case SVC_DC: 245 247 return adf_fw_dc_config; ··· 249 253 case SVC_ASYM: 250 254 return adf_fw_asym_config; 251 255 case SVC_ASYM_DC: 252 - case SVC_DC_ASYM: 253 256 return adf_fw_asym_dc_config; 254 257 case SVC_SYM_DC: 255 - case SVC_DC_SYM: 256 258 return adf_fw_sym_dc_config; 257 259 default: 258 260 return NULL; ··· 460 466 hw_data->get_hb_clock = adf_gen4_get_heartbeat_clock; 461 467 hw_data->num_hb_ctrs = ADF_NUM_HB_CNT_PER_AE; 462 468 hw_data->clock_frequency = ADF_4XXX_AE_FREQ; 469 + hw_data->services_supported = adf_gen4_services_supported; 463 470 464 471 adf_gen4_set_err_mask(&hw_data->dev_err_mask); 465 472 adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
+1
drivers/crypto/intel/qat/qat_common/adf_accel_devices.h
··· 333 333 int (*get_rp_group)(struct adf_accel_dev *accel_dev, u32 ae_mask); 334 334 u32 (*get_ena_thd_mask)(struct adf_accel_dev *accel_dev, u32 obj_num); 335 335 int (*dev_config)(struct adf_accel_dev *accel_dev); 336 + bool (*services_supported)(unsigned long mask); 336 337 struct adf_pfvf_ops pfvf_ops; 337 338 struct adf_hw_csr_ops csr_ops; 338 339 struct adf_dc_ops dc_ops;
+147 -19
drivers/crypto/intel/qat/qat_common/adf_cfg_services.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* Copyright(c) 2023 Intel Corporation */ 3 3 4 + #include <linux/array_size.h> 5 + #include <linux/bitops.h> 4 6 #include <linux/export.h> 5 7 #include <linux/pci.h> 6 8 #include <linux/string.h> ··· 10 8 #include "adf_cfg_services.h" 11 9 #include "adf_cfg_strings.h" 12 10 13 - const char *const adf_cfg_services[] = { 14 - [SVC_CY] = ADF_CFG_CY, 15 - [SVC_CY2] = ADF_CFG_ASYM_SYM, 11 + static const char *const adf_cfg_services[] = { 12 + [SVC_ASYM] = ADF_CFG_ASYM, 13 + [SVC_SYM] = ADF_CFG_SYM, 16 14 [SVC_DC] = ADF_CFG_DC, 17 15 [SVC_DCC] = ADF_CFG_DCC, 18 - [SVC_SYM] = ADF_CFG_SYM, 19 - [SVC_ASYM] = ADF_CFG_ASYM, 20 - [SVC_DC_ASYM] = ADF_CFG_DC_ASYM, 21 - [SVC_ASYM_DC] = ADF_CFG_ASYM_DC, 22 - [SVC_DC_SYM] = ADF_CFG_DC_SYM, 23 - [SVC_SYM_DC] = ADF_CFG_SYM_DC, 24 16 }; 25 17 26 - int adf_get_service_enabled(struct adf_accel_dev *accel_dev) 18 + /* 19 + * Ensure that the size of the array matches the number of services, 20 + * SVC_BASE_COUNT, that is used to size the bitmap. 21 + */ 22 + static_assert(ARRAY_SIZE(adf_cfg_services) == SVC_BASE_COUNT); 23 + 24 + /* 25 + * Ensure that the maximum number of concurrent services that can be 26 + * enabled on a device is less than or equal to the number of total 27 + * supported services. 28 + */ 29 + static_assert(ARRAY_SIZE(adf_cfg_services) >= MAX_NUM_CONCURR_SVC); 30 + 31 + /* 32 + * Ensure that the number of services fit a single unsigned long, as each 33 + * service is represented by a bit in the mask. 34 + */ 35 + static_assert(BITS_PER_LONG >= SVC_BASE_COUNT); 36 + 37 + /* 38 + * Ensure that size of the concatenation of all service strings is smaller 39 + * than the size of the buffer that will contain them. 40 + */ 41 + static_assert(sizeof(ADF_CFG_SYM ADF_SERVICES_DELIMITER 42 + ADF_CFG_ASYM ADF_SERVICES_DELIMITER 43 + ADF_CFG_DC ADF_SERVICES_DELIMITER 44 + ADF_CFG_DCC) < ADF_CFG_MAX_VAL_LEN_IN_BYTES); 45 + 46 + static int adf_service_string_to_mask(struct adf_accel_dev *accel_dev, const char *buf, 47 + size_t len, unsigned long *out_mask) 27 48 { 28 - char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; 49 + struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev); 50 + char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; 51 + unsigned long mask = 0; 52 + char *substr, *token; 53 + int id, num_svc = 0; 54 + 55 + if (len > ADF_CFG_MAX_VAL_LEN_IN_BYTES - 1) 56 + return -EINVAL; 57 + 58 + strscpy(services, buf, ADF_CFG_MAX_VAL_LEN_IN_BYTES); 59 + substr = services; 60 + 61 + while ((token = strsep(&substr, ADF_SERVICES_DELIMITER))) { 62 + id = sysfs_match_string(adf_cfg_services, token); 63 + if (id < 0) 64 + return id; 65 + 66 + if (test_and_set_bit(id, &mask)) 67 + return -EINVAL; 68 + 69 + if (num_svc++ == MAX_NUM_CONCURR_SVC) 70 + return -EINVAL; 71 + } 72 + 73 + if (hw_data->services_supported && !hw_data->services_supported(mask)) 74 + return -EINVAL; 75 + 76 + *out_mask = mask; 77 + 78 + return 0; 79 + } 80 + 81 + static int adf_service_mask_to_string(unsigned long mask, char *buf, size_t len) 82 + { 83 + int offset = 0; 84 + int bit; 85 + 86 + if (len < ADF_CFG_MAX_VAL_LEN_IN_BYTES) 87 + return -ENOSPC; 88 + 89 + for_each_set_bit(bit, &mask, SVC_BASE_COUNT) { 90 + if (offset) 91 + offset += scnprintf(buf + offset, len - offset, 92 + ADF_SERVICES_DELIMITER); 93 + 94 + offset += scnprintf(buf + offset, len - offset, "%s", 95 + adf_cfg_services[bit]); 96 + } 97 + 98 + return 0; 99 + } 100 + 101 + int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in, 102 + size_t in_len, char *out, size_t out_len) 103 + { 104 + unsigned long mask; 105 + int ret; 106 + 107 + ret = adf_service_string_to_mask(accel_dev, in, in_len, &mask); 108 + if (ret) 109 + return ret; 110 + 111 + if (!mask) 112 + return -EINVAL; 113 + 114 + return adf_service_mask_to_string(mask, out, out_len); 115 + } 116 + 117 + static int adf_get_service_mask(struct adf_accel_dev *accel_dev, unsigned long *mask) 118 + { 119 + char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; 120 + size_t len; 29 121 int ret; 30 122 31 123 ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, 32 124 ADF_SERVICES_ENABLED, services); 33 125 if (ret) { 34 - dev_err(&GET_DEV(accel_dev), 35 - ADF_SERVICES_ENABLED " param not found\n"); 126 + dev_err(&GET_DEV(accel_dev), "%s param not found\n", 127 + ADF_SERVICES_ENABLED); 36 128 return ret; 37 129 } 38 130 39 - ret = match_string(adf_cfg_services, ARRAY_SIZE(adf_cfg_services), 40 - services); 41 - if (ret < 0) 42 - dev_err(&GET_DEV(accel_dev), 43 - "Invalid value of " ADF_SERVICES_ENABLED " param: %s\n", 44 - services); 131 + len = strnlen(services, ADF_CFG_MAX_VAL_LEN_IN_BYTES); 132 + ret = adf_service_string_to_mask(accel_dev, services, len, mask); 133 + if (ret) 134 + dev_err(&GET_DEV(accel_dev), "Invalid value of %s param: %s\n", 135 + ADF_SERVICES_ENABLED, services); 45 136 46 137 return ret; 138 + } 139 + 140 + int adf_get_service_enabled(struct adf_accel_dev *accel_dev) 141 + { 142 + unsigned long mask; 143 + int ret; 144 + 145 + ret = adf_get_service_mask(accel_dev, &mask); 146 + if (ret) 147 + return ret; 148 + 149 + if (test_bit(SVC_SYM, &mask) && test_bit(SVC_ASYM, &mask)) 150 + return SVC_SYM_ASYM; 151 + 152 + if (test_bit(SVC_SYM, &mask) && test_bit(SVC_DC, &mask)) 153 + return SVC_SYM_DC; 154 + 155 + if (test_bit(SVC_ASYM, &mask) && test_bit(SVC_DC, &mask)) 156 + return SVC_ASYM_DC; 157 + 158 + if (test_bit(SVC_SYM, &mask)) 159 + return SVC_SYM; 160 + 161 + if (test_bit(SVC_ASYM, &mask)) 162 + return SVC_ASYM; 163 + 164 + if (test_bit(SVC_DC, &mask)) 165 + return SVC_DC; 166 + 167 + if (test_bit(SVC_DCC, &mask)) 168 + return SVC_DCC; 169 + 170 + return -EINVAL; 47 171 } 48 172 EXPORT_SYMBOL_GPL(adf_get_service_enabled);
+18 -10
drivers/crypto/intel/qat/qat_common/adf_cfg_services.h
··· 8 8 struct adf_accel_dev; 9 9 10 10 enum adf_services { 11 - SVC_CY = 0, 12 - SVC_CY2, 11 + SVC_ASYM = 0, 12 + SVC_SYM, 13 13 SVC_DC, 14 14 SVC_DCC, 15 - SVC_SYM, 16 - SVC_ASYM, 17 - SVC_DC_ASYM, 18 - SVC_ASYM_DC, 19 - SVC_DC_SYM, 20 - SVC_SYM_DC, 21 - SVC_COUNT 15 + SVC_BASE_COUNT 22 16 }; 23 17 24 - extern const char *const adf_cfg_services[SVC_COUNT]; 18 + enum adf_composed_services { 19 + SVC_SYM_ASYM = SVC_BASE_COUNT, 20 + SVC_SYM_DC, 21 + SVC_ASYM_DC, 22 + }; 25 23 24 + enum { 25 + ADF_ONE_SERVICE = 1, 26 + ADF_TWO_SERVICES, 27 + ADF_THREE_SERVICES, 28 + }; 29 + 30 + #define MAX_NUM_CONCURR_SVC ADF_THREE_SERVICES 31 + 32 + int adf_parse_service_string(struct adf_accel_dev *accel_dev, const char *in, 33 + size_t in_len, char *out, size_t out_len); 26 34 int adf_get_service_enabled(struct adf_accel_dev *accel_dev); 27 35 28 36 #endif
+1 -5
drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
··· 27 27 #define ADF_CFG_CY "sym;asym" 28 28 #define ADF_CFG_SYM "sym" 29 29 #define ADF_CFG_ASYM "asym" 30 - #define ADF_CFG_ASYM_SYM "asym;sym" 31 - #define ADF_CFG_ASYM_DC "asym;dc" 32 - #define ADF_CFG_DC_ASYM "dc;asym" 33 - #define ADF_CFG_SYM_DC "sym;dc" 34 - #define ADF_CFG_DC_SYM "dc;sym" 35 30 #define ADF_CFG_DCC "dcc" 36 31 #define ADF_SERVICES_ENABLED "ServicesEnabled" 32 + #define ADF_SERVICES_DELIMITER ";" 37 33 #define ADF_PM_IDLE_SUPPORT "PmIdleSupport" 38 34 #define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled" 39 35 #define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \
+2 -13
drivers/crypto/intel/qat/qat_common/adf_gen4_config.c
··· 213 213 */ 214 214 int adf_gen4_dev_config(struct adf_accel_dev *accel_dev) 215 215 { 216 - char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0}; 217 216 int ret; 218 217 219 218 ret = adf_cfg_section_add(accel_dev, ADF_KERNEL_SEC); ··· 223 224 if (ret) 224 225 goto err; 225 226 226 - ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, 227 - ADF_SERVICES_ENABLED, services); 228 - if (ret) 229 - goto err; 230 - 231 - ret = sysfs_match_string(adf_cfg_services, services); 232 - if (ret < 0) 233 - goto err; 234 - 235 - switch (ret) { 236 - case SVC_CY: 237 - case SVC_CY2: 227 + switch (adf_get_service_enabled(accel_dev)) { 228 + case SVC_SYM_ASYM: 238 229 ret = adf_crypto_dev_config(accel_dev); 239 230 break; 240 231 case SVC_DC:
+19 -7
drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.c
··· 1 1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) 2 2 /* Copyright(c) 2020 Intel Corporation */ 3 + #include <linux/bitops.h> 3 4 #include <linux/iopoll.h> 4 5 #include <asm/div64.h> 5 6 #include "adf_accel_devices.h" ··· 266 265 case SVC_SYM: 267 266 case SVC_ASYM: 268 267 return true; 269 - case SVC_CY: 270 - case SVC_CY2: 271 - case SVC_DCC: 272 - case SVC_ASYM_DC: 273 - case SVC_DC_ASYM: 274 - case SVC_SYM_DC: 275 - case SVC_DC_SYM: 276 268 default: 277 269 return false; 278 270 } 279 271 } 272 + 273 + bool adf_gen4_services_supported(unsigned long mask) 274 + { 275 + unsigned long num_svc = hweight_long(mask); 276 + 277 + if (mask >= BIT(SVC_BASE_COUNT)) 278 + return false; 279 + 280 + switch (num_svc) { 281 + case ADF_ONE_SERVICE: 282 + return true; 283 + case ADF_TWO_SERVICES: 284 + return !test_bit(SVC_DCC, &mask); 285 + default: 286 + return false; 287 + } 288 + } 289 + EXPORT_SYMBOL_GPL(adf_gen4_services_supported); 280 290 281 291 int adf_gen4_init_thd2arb_map(struct adf_accel_dev *accel_dev) 282 292 {
+1
drivers/crypto/intel/qat/qat_common/adf_gen4_hw_data.h
··· 179 179 struct bank_state *state); 180 180 int adf_gen4_bank_state_restore(struct adf_accel_dev *accel_dev, 181 181 u32 bank_number, struct bank_state *state); 182 + bool adf_gen4_services_supported(unsigned long service_mask); 182 183 183 184 #endif
+7 -5
drivers/crypto/intel/qat/qat_common/adf_sysfs.c
··· 116 116 static ssize_t cfg_services_store(struct device *dev, struct device_attribute *attr, 117 117 const char *buf, size_t count) 118 118 { 119 + char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { }; 119 120 struct adf_hw_device_data *hw_data; 120 121 struct adf_accel_dev *accel_dev; 121 122 int ret; 122 123 123 - ret = sysfs_match_string(adf_cfg_services, buf); 124 - if (ret < 0) 125 - return ret; 126 - 127 124 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev)); 128 125 if (!accel_dev) 129 126 return -EINVAL; 127 + 128 + ret = adf_parse_service_string(accel_dev, buf, count, services, 129 + ADF_CFG_MAX_VAL_LEN_IN_BYTES); 130 + if (ret) 131 + return ret; 130 132 131 133 if (adf_dev_started(accel_dev)) { 132 134 dev_info(dev, "Device qat_dev%d must be down to reconfigure the service.\n", ··· 136 134 return -EINVAL; 137 135 } 138 136 139 - ret = adf_sysfs_update_dev_config(accel_dev, adf_cfg_services[ret]); 137 + ret = adf_sysfs_update_dev_config(accel_dev, services); 140 138 if (ret < 0) 141 139 return ret; 142 140