1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 #include "adf_cfg_instance.h"
5 #include "adf_cfg_section.h"
6 #include "adf_cfg_device.h"
7 #include "icp_qat_hw.h"
8 #include "adf_common_drv.h"
9 
10 #define ADF_CFG_SVCS_MAX (25)
11 #define ADF_CFG_DEPRE_PARAMS_NUM (4)
12 
13 #define ADF_CFG_CAP_DC ADF_ACCEL_CAPABILITIES_COMPRESSION
14 #define ADF_CFG_CAP_ASYM ADF_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC
15 #define ADF_CFG_CAP_SYM                                                        \
16 	(ADF_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC |                             \
17 	 ADF_ACCEL_CAPABILITIES_CIPHER |                                       \
18 	 ADF_ACCEL_CAPABILITIES_AUTHENTICATION)
19 #define ADF_CFG_CAP_CY (ADF_CFG_CAP_ASYM | ADF_CFG_CAP_SYM)
20 
21 #define ADF_CFG_FW_CAP_RL ICP_ACCEL_CAPABILITIES_RL
22 #define ADF_CFG_FW_CAP_HKDF ICP_ACCEL_CAPABILITIES_HKDF
23 #define ADF_CFG_FW_CAP_ECEDMONT ICP_ACCEL_CAPABILITIES_ECEDMONT
24 #define ADF_CFG_FW_CAP_EXT_ALGCHAIN ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN
25 
26 #define ADF_CFG_CY_RINGS                                                       \
27 	(CRYPTO | CRYPTO << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                   \
28 	 CRYPTO << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                            \
29 	 CRYPTO << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
30 
31 #define ADF_CFG_SYM_RINGS                                                      \
32 	(SYM | SYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                         \
33 	 SYM << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                               \
34 	 SYM << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
35 
36 #define ADF_CFG_ASYM_RINGS                                                     \
37 	(ASYM | ASYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                       \
38 	 ASYM << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                              \
39 	 ASYM << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
40 
41 #define ADF_CFG_CY_DC_RINGS                                                    \
42 	(CRYPTO | CRYPTO << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                   \
43 	 NA << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                                \
44 	 COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
45 
46 #define ADF_CFG_ASYM_DC_RINGS                                                  \
47 	(ASYM | ASYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                       \
48 	 COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                              \
49 	 COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
50 
51 #define ADF_CFG_SYM_DC_RINGS                                                   \
52 	(SYM | SYM << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                         \
53 	 COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                              \
54 	 COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
55 
56 #define ADF_CFG_DC_RINGS                                                       \
57 	(COMP | COMP << ADF_CFG_SERV_RING_PAIR_1_SHIFT |                       \
58 	 COMP << ADF_CFG_SERV_RING_PAIR_2_SHIFT |                              \
59 	 COMP << ADF_CFG_SERV_RING_PAIR_3_SHIFT)
60 
61 static char adf_cfg_deprecated_params[][ADF_CFG_MAX_KEY_LEN_IN_BYTES] =
62     { ADF_DEV_KPT_ENABLE,
63       ADF_STORAGE_FIRMWARE_ENABLED,
64       ADF_RL_FIRMWARE_ENABLED,
65       ADF_PKE_DISABLED };
66 
67 struct adf_cfg_enabled_services {
68 	const char svcs_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
69 	u16 rng_to_svc_msk;
70 	u32 enabled_svc_cap;
71 	u32 enabled_fw_cap;
72 };
73 
74 struct adf_cfg_profile {
75 	enum adf_cfg_fw_image_type fw_image_type;
76 	struct adf_cfg_enabled_services supported_svcs[ADF_CFG_SVCS_MAX];
77 };
78 
79 static struct adf_cfg_profile adf_profiles[] =
80     { { ADF_FW_IMAGE_DEFAULT,
81 	{
82 	    { "cy",
83 	      ADF_CFG_CY_RINGS,
84 	      ADF_CFG_CAP_CY,
85 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
86 	    { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 },
87 	    { "sym",
88 	      ADF_CFG_SYM_RINGS,
89 	      ADF_CFG_CAP_SYM,
90 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
91 	    { "asym",
92 	      ADF_CFG_ASYM_RINGS,
93 	      ADF_CFG_CAP_ASYM,
94 	      ADF_CFG_FW_CAP_ECEDMONT },
95 	    { "cy;dc",
96 	      ADF_CFG_CY_DC_RINGS,
97 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
98 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
99 	    { "dc;cy",
100 	      ADF_CFG_CY_DC_RINGS,
101 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
102 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
103 	    { "asym;dc",
104 	      ADF_CFG_ASYM_DC_RINGS,
105 	      ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC,
106 	      ADF_CFG_FW_CAP_ECEDMONT },
107 	    { "dc;asym",
108 	      ADF_CFG_ASYM_DC_RINGS,
109 	      ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC,
110 	      ADF_CFG_FW_CAP_ECEDMONT },
111 	    { "sym;dc",
112 	      ADF_CFG_SYM_DC_RINGS,
113 	      ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC,
114 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
115 	    { "dc;sym",
116 	      ADF_CFG_SYM_DC_RINGS,
117 	      ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC,
118 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
119 	    { "inline;sym",
120 	      ADF_CFG_SYM_RINGS,
121 	      ADF_CFG_CAP_SYM,
122 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
123 	    { "sym;inline",
124 	      ADF_CFG_SYM_RINGS,
125 	      ADF_CFG_CAP_SYM,
126 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
127 	    { "inline;asym",
128 	      ADF_CFG_SYM_RINGS,
129 	      ADF_CFG_CAP_SYM,
130 	      ADF_CFG_FW_CAP_EXT_ALGCHAIN },
131 	    { "asym;inline",
132 	      ADF_CFG_ASYM_RINGS,
133 	      ADF_CFG_CAP_ASYM,
134 	      ADF_CFG_FW_CAP_ECEDMONT },
135 	    { "inline", 0, 0, 0 },
136 	    { "inline;cy",
137 	      ADF_CFG_CY_RINGS,
138 	      ADF_CFG_CAP_CY,
139 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
140 	    { "cy;inline",
141 	      ADF_CFG_CY_RINGS,
142 	      ADF_CFG_CAP_CY,
143 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
144 	    { "dc;inline", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 },
145 	    { "inline;dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 },
146 	    { "cy;dc;inline",
147 	      ADF_CFG_CY_DC_RINGS,
148 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
149 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
150 	    { "cy;inline;dc",
151 	      ADF_CFG_CY_DC_RINGS,
152 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
153 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
154 	    { "dc;inline;cy",
155 	      ADF_CFG_CY_DC_RINGS,
156 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
157 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
158 	    { "dc;cy;inline",
159 	      ADF_CFG_CY_DC_RINGS,
160 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
161 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
162 	    { "inline;cy;dc",
163 	      ADF_CFG_CY_DC_RINGS,
164 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
165 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
166 	    { "inline;dc;cy",
167 	      ADF_CFG_CY_DC_RINGS,
168 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
169 	      ADF_CFG_FW_CAP_ECEDMONT | ADF_CFG_FW_CAP_EXT_ALGCHAIN },
170 	} },
171       { ADF_FW_IMAGE_CRYPTO,
172 	{
173 	    { "cy",
174 	      ADF_CFG_CY_RINGS,
175 	      ADF_CFG_CAP_CY,
176 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
177 		  ADF_CFG_FW_CAP_ECEDMONT |
178 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
179 	    { "sym",
180 	      ADF_CFG_SYM_RINGS,
181 	      ADF_CFG_CAP_SYM,
182 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
183 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
184 	    { "asym",
185 	      ADF_CFG_ASYM_RINGS,
186 	      ADF_CFG_CAP_ASYM,
187 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT },
188 	} },
189       { ADF_FW_IMAGE_COMPRESSION,
190 	{
191 	    { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 },
192 	} },
193       { ADF_FW_IMAGE_CUSTOM1,
194 	{
195 	    { "cy",
196 	      ADF_CFG_CY_RINGS,
197 	      ADF_CFG_CAP_CY,
198 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
199 		  ADF_CFG_FW_CAP_ECEDMONT |
200 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
201 	    { "dc", ADF_CFG_DC_RINGS, ADF_CFG_CAP_DC, 0 },
202 	    { "sym",
203 	      ADF_CFG_SYM_RINGS,
204 	      ADF_CFG_CAP_SYM,
205 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
206 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
207 	    { "asym",
208 	      ADF_CFG_ASYM_RINGS,
209 	      ADF_CFG_CAP_ASYM,
210 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT },
211 	    { "cy;dc",
212 	      ADF_CFG_CY_DC_RINGS,
213 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
214 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
215 		  ADF_CFG_FW_CAP_ECEDMONT |
216 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
217 	    { "dc;cy",
218 	      ADF_CFG_CY_DC_RINGS,
219 	      ADF_CFG_CAP_CY | ADF_CFG_CAP_DC,
220 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
221 		  ADF_CFG_FW_CAP_ECEDMONT |
222 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
223 	    { "asym;dc",
224 	      ADF_CFG_ASYM_DC_RINGS,
225 	      ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC,
226 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT },
227 	    { "dc;asym",
228 	      ADF_CFG_ASYM_DC_RINGS,
229 	      ADF_CFG_CAP_ASYM | ADF_CFG_CAP_DC,
230 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_ECEDMONT },
231 	    { "sym;dc",
232 	      ADF_CFG_SYM_DC_RINGS,
233 	      ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC,
234 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
235 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
236 	    { "dc;sym",
237 	      ADF_CFG_SYM_DC_RINGS,
238 	      ADF_CFG_CAP_SYM | ADF_CFG_CAP_DC,
239 	      ADF_CFG_FW_CAP_RL | ADF_CFG_FW_CAP_HKDF |
240 		  ADF_CFG_FW_CAP_EXT_ALGCHAIN },
241 	} } };
242 
243 int
244 adf_cfg_get_ring_pairs(struct adf_cfg_device *device,
245 		       struct adf_cfg_instance *inst,
246 		       const char *process_name,
247 		       struct adf_accel_dev *accel_dev)
248 {
249 	int i = 0;
250 	int ret = EFAULT;
251 	struct adf_cfg_instance *free_inst = NULL;
252 	enum adf_cfg_bundle_type free_bundle_type;
253 	int first_user_bundle = 0;
254 
255 	/* Section of user process with poll mode */
256 	if (strcmp(ADF_KERNEL_SEC, process_name) &&
257 	    strcmp(ADF_KERNEL_SAL_SEC, process_name) &&
258 	    inst->polling_mode == ADF_CFG_RESP_POLL) {
259 		first_user_bundle = device->max_kernel_bundle_nr + 1;
260 		for (i = first_user_bundle; i < device->bundle_num; i++) {
261 			free_inst = adf_cfg_get_free_instance(
262 			    device, device->bundles[i], inst, process_name);
263 
264 			if (!free_inst)
265 				continue;
266 
267 			ret = adf_cfg_get_ring_pairs_from_bundle(
268 			    device->bundles[i], inst, process_name, free_inst);
269 			return ret;
270 		}
271 	} else {
272 		/* Section of in-tree, or kernel API or user process
273 		 * with epoll mode
274 		 */
275 		if (!strcmp(ADF_KERNEL_SEC, process_name) ||
276 		    !strcmp(ADF_KERNEL_SAL_SEC, process_name))
277 			free_bundle_type = KERNEL;
278 		else
279 			free_bundle_type = USER;
280 
281 		for (i = 0; i < device->bundle_num; i++) {
282 			/* Since both in-tree and kernel API's bundle type
283 			 * are kernel, use cpumask_subset to check if the
284 			 * ring's affinity mask is a subset of a bundle's
285 			 * one.
286 			 */
287 			if (free_bundle_type == device->bundles[i]->type &&
288 			    CPU_SUBSET(&device->bundles[i]->affinity_mask,
289 				       &inst->affinity_mask)) {
290 				free_inst = adf_cfg_get_free_instance(
291 				    device,
292 				    device->bundles[i],
293 				    inst,
294 				    process_name);
295 
296 				if (!free_inst)
297 					continue;
298 				ret = adf_cfg_get_ring_pairs_from_bundle(
299 				    device->bundles[i],
300 				    inst,
301 				    process_name,
302 				    free_inst);
303 
304 				return ret;
305 
306 			}
307 		}
308 		for (i = 0; i < device->bundle_num; i++) {
309 			if (adf_cfg_is_free(device->bundles[i])) {
310 				free_inst = adf_cfg_get_free_instance(
311 				    device,
312 				    device->bundles[i],
313 				    inst,
314 				    process_name);
315 				if (!free_inst)
316 					continue;
317 
318 				ret = adf_cfg_get_ring_pairs_from_bundle(
319 				    device->bundles[i],
320 				    inst,
321 				    process_name,
322 				    free_inst);
323 				return ret;
324 			}
325 		}
326 	}
327 	pr_err("Don't have enough rings for instance %s in process %s\n",
328 	       inst->name,
329 	       process_name);
330 
331 	return ret;
332 }
333 
334 int
335 adf_cfg_get_services_enabled(struct adf_accel_dev *accel_dev,
336 			     u16 *ring_to_svc_map)
337 {
338 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
339 	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
340 	u32 i = 0;
341 	struct adf_cfg_enabled_services *svcs = NULL;
342 	enum adf_cfg_fw_image_type fw_image_type = ADF_FW_IMAGE_DEFAULT;
343 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
344 	*ring_to_svc_map = 0;
345 
346 	/* Get the services enabled by user */
347 	snprintf(key, sizeof(key), ADF_SERVICES_ENABLED);
348 	if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val))
349 		return EFAULT;
350 
351 	if (hw_data->get_fw_image_type) {
352 		if (hw_data->get_fw_image_type(accel_dev, &fw_image_type))
353 			return EFAULT;
354 	}
355 
356 	for (i = 0; i < ADF_CFG_SVCS_MAX; i++) {
357 		svcs = &adf_profiles[fw_image_type].supported_svcs[i];
358 
359 		if (!strncmp(svcs->svcs_enabled,
360 			     "",
361 			     ADF_CFG_MAX_VAL_LEN_IN_BYTES))
362 			break;
363 
364 		if (!strncmp(val,
365 			     svcs->svcs_enabled,
366 			     ADF_CFG_MAX_VAL_LEN_IN_BYTES)) {
367 			*ring_to_svc_map = svcs->rng_to_svc_msk;
368 			return 0;
369 		}
370 	}
371 
372 	device_printf(GET_DEV(accel_dev),
373 		      "Invalid ServicesEnabled %s for ServicesProfile: %d\n",
374 		      val,
375 		      fw_image_type);
376 
377 	return EFAULT;
378 }
379 
380 void
381 adf_cfg_set_asym_rings_mask(struct adf_accel_dev *accel_dev)
382 {
383 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
384 
385 	hw_data->asym_rings_mask = 0;
386 }
387 
388 void
389 adf_cfg_gen_dispatch_arbiter(struct adf_accel_dev *accel_dev,
390 			     const u32 *thrd_to_arb_map,
391 			     u32 *thrd_to_arb_map_gen,
392 			     u32 total_engines)
393 {
394 	int engine, thread, service, bits;
395 	u32 thread_ability, ability_map, service_mask, service_type;
396 	u16 ena_srv_mask = GET_HW_DATA(accel_dev)->ring_to_svc_map;
397 
398 	for (engine = 0; engine < total_engines; engine++) {
399 		if (!(GET_HW_DATA(accel_dev)->ae_mask & (1 << engine)))
400 			continue;
401 		bits = 0;
402 		/* ability_map is used to indicate the threads ability */
403 		ability_map = thrd_to_arb_map[engine];
404 		thrd_to_arb_map_gen[engine] = 0;
405 		/* parse each thread on the engine */
406 		for (thread = 0; thread < ADF_NUM_THREADS_PER_AE; thread++) {
407 			/* get the ability of this thread */
408 			thread_ability = ability_map & ADF_THRD_ABILITY_MASK;
409 			ability_map >>= ADF_THRD_ABILITY_BIT_LEN;
410 			/* parse each service */
411 			for (service = 0; service < ADF_CFG_MAX_SERVICES;
412 			     service++) {
413 				service_type =
414 				    GET_SRV_TYPE(ena_srv_mask, service);
415 				switch (service_type) {
416 				case CRYPTO:
417 					service_mask = ADF_CFG_ASYM_SRV_MASK;
418 					if (thread_ability & service_mask)
419 						thrd_to_arb_map_gen[engine] |=
420 						    (1 << bits);
421 					bits++;
422 					service++;
423 					service_mask = ADF_CFG_SYM_SRV_MASK;
424 					break;
425 				case COMP:
426 					service_mask = ADF_CFG_DC_SRV_MASK;
427 					break;
428 				case SYM:
429 					service_mask = ADF_CFG_SYM_SRV_MASK;
430 					break;
431 				case ASYM:
432 					service_mask = ADF_CFG_ASYM_SRV_MASK;
433 					break;
434 				default:
435 					service_mask = ADF_CFG_UNKNOWN_SRV_MASK;
436 				}
437 				if (thread_ability & service_mask)
438 					thrd_to_arb_map_gen[engine] |=
439 					    (1 << bits);
440 				bits++;
441 			}
442 		}
443 	}
444 }
445 
446 int
447 adf_cfg_get_fw_image_type(struct adf_accel_dev *accel_dev,
448 			  enum adf_cfg_fw_image_type *fw_image_type)
449 {
450 	*fw_image_type = ADF_FW_IMAGE_CUSTOM1;
451 
452 	return 0;
453 }
454 
455 static int
456 adf_cfg_get_caps_enabled(struct adf_accel_dev *accel_dev,
457 			 u32 *enabled_svc_caps,
458 			 u32 *enabled_fw_caps)
459 {
460 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
461 	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
462 	u8 i = 0;
463 	struct adf_cfg_enabled_services *svcs = NULL;
464 	enum adf_cfg_fw_image_type fw_image_type = ADF_FW_IMAGE_DEFAULT;
465 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
466 
467 	*enabled_svc_caps = 0;
468 	*enabled_fw_caps = 0;
469 
470 	/* Get the services enabled by user */
471 	snprintf(key, sizeof(key), ADF_SERVICES_ENABLED);
472 	if (adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC, key, val))
473 		return EFAULT;
474 
475 	/*
476 	 * Only the PF driver has the hook for get_fw_image_type as the VF's
477 	 * enabled service is from PFVF communication. The fw_image_type for
478 	 * the VF is set to DEFAULT since this type contains all kinds of
479 	 * enabled service.
480 	 */
481 	if (hw_data->get_fw_image_type) {
482 		if (hw_data->get_fw_image_type(accel_dev, &fw_image_type))
483 			return EFAULT;
484 	}
485 
486 	for (i = 0; i < ADF_CFG_SVCS_MAX; i++) {
487 		svcs = &adf_profiles[fw_image_type].supported_svcs[i];
488 
489 		if (!strncmp(svcs->svcs_enabled,
490 			     "",
491 			     ADF_CFG_MAX_VAL_LEN_IN_BYTES))
492 			break;
493 
494 		if (!strncmp(val,
495 			     svcs->svcs_enabled,
496 			     ADF_CFG_MAX_VAL_LEN_IN_BYTES)) {
497 			*enabled_svc_caps = svcs->enabled_svc_cap;
498 			*enabled_fw_caps = svcs->enabled_fw_cap;
499 			return 0;
500 		}
501 	}
502 	device_printf(GET_DEV(accel_dev),
503 		      "Invalid ServicesEnabled %s for ServicesProfile: %d\n",
504 		      val,
505 		      fw_image_type);
506 
507 	return EFAULT;
508 }
509 
510 static void
511 adf_cfg_check_deprecated_params(struct adf_accel_dev *accel_dev)
512 {
513 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
514 	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
515 	u8 i = 0;
516 
517 	for (i = 0; i < ADF_CFG_DEPRE_PARAMS_NUM; i++) {
518 		/* give a warning if the deprecated params are set by user */
519 		snprintf(key, sizeof(key), "%s", adf_cfg_deprecated_params[i]);
520 		if (!adf_cfg_get_param_value(
521 			accel_dev, ADF_GENERAL_SEC, key, val)) {
522 			device_printf(GET_DEV(accel_dev),
523 				      "Parameter '%s' has been deprecated\n",
524 				      key);
525 		}
526 	}
527 }
528 
529 static int
530 adf_cfg_check_enabled_services(struct adf_accel_dev *accel_dev,
531 			       u32 enabled_svc_caps)
532 {
533 	u32 hw_caps = GET_HW_DATA(accel_dev)->accel_capabilities_mask;
534 
535 	if ((enabled_svc_caps & hw_caps) == enabled_svc_caps)
536 		return 0;
537 
538 	device_printf(GET_DEV(accel_dev), "Unsupported device configuration\n");
539 
540 	return EFAULT;
541 }
542 
543 static int
544 adf_cfg_update_pf_accel_cap_mask(struct adf_accel_dev *accel_dev)
545 {
546 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
547 	u32 enabled_svc_caps = 0;
548 	u32 enabled_fw_caps = 0;
549 
550 	if (hw_data->get_accel_cap) {
551 		hw_data->accel_capabilities_mask =
552 		    hw_data->get_accel_cap(accel_dev);
553 	}
554 
555 	if (adf_cfg_get_caps_enabled(accel_dev,
556 				     &enabled_svc_caps,
557 				     &enabled_fw_caps))
558 		return EFAULT;
559 
560 	if (adf_cfg_check_enabled_services(accel_dev, enabled_svc_caps))
561 		return EFAULT;
562 
563 	if (!(enabled_svc_caps & ADF_CFG_CAP_ASYM))
564 		hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_ASYM;
565 	if (!(enabled_svc_caps & ADF_CFG_CAP_SYM))
566 		hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_SYM;
567 	if (!(enabled_svc_caps & ADF_CFG_CAP_DC))
568 		hw_data->accel_capabilities_mask &= ~ADF_CFG_CAP_DC;
569 
570 	/* Enable FW defined capabilities*/
571 	if (enabled_fw_caps)
572 		hw_data->accel_capabilities_mask |= enabled_fw_caps;
573 
574 	return 0;
575 }
576 
577 static int
578 adf_cfg_update_vf_accel_cap_mask(struct adf_accel_dev *accel_dev)
579 {
580 	u32 enabled_svc_caps = 0;
581 	u32 enabled_fw_caps = 0;
582 
583 	if (adf_cfg_get_caps_enabled(accel_dev,
584 				     &enabled_svc_caps,
585 				     &enabled_fw_caps))
586 		return EFAULT;
587 
588 	if (adf_cfg_check_enabled_services(accel_dev, enabled_svc_caps))
589 		return EFAULT;
590 
591 	return 0;
592 }
593 
594 int
595 adf_cfg_device_init(struct adf_cfg_device *device,
596 		    struct adf_accel_dev *accel_dev)
597 {
598 	int i = 0;
599 	/* max_inst indicates the max instance number one bank can hold */
600 	int max_inst = accel_dev->hw_device->tx_rx_gap;
601 	int ret = ENOMEM;
602 	struct adf_hw_device_data *hw_data = GET_HW_DATA(accel_dev);
603 
604 	adf_cfg_check_deprecated_params(accel_dev);
605 
606 	device->bundle_num = 0;
607 	device->bundles = (struct adf_cfg_bundle **)malloc(
608 	    sizeof(struct adf_cfg_bundle *) * accel_dev->hw_device->num_banks,
609 	    M_QAT,
610 	    M_WAITOK | M_ZERO);
611 
612 	device->bundle_num = accel_dev->hw_device->num_banks;
613 
614 	device->instances = (struct adf_cfg_instance **)malloc(
615 	    sizeof(struct adf_cfg_instance *) * device->bundle_num * max_inst,
616 	    M_QAT,
617 	    M_WAITOK | M_ZERO);
618 
619 	device->instance_index = 0;
620 
621 	device->max_kernel_bundle_nr = -1;
622 
623 	ret = EFAULT;
624 
625 	/* Update the acceleration capability mask based on User capability */
626 	if (!accel_dev->is_vf) {
627 		if (adf_cfg_update_pf_accel_cap_mask(accel_dev))
628 			goto failed;
629 	} else {
630 		if (adf_cfg_update_vf_accel_cap_mask(accel_dev))
631 			goto failed;
632 	}
633 
634 	/* Based on the svc configured, get ring_to_svc_map */
635 	if (hw_data->get_ring_to_svc_map) {
636 		if (hw_data->get_ring_to_svc_map(accel_dev,
637 						 &hw_data->ring_to_svc_map))
638 			goto failed;
639 	}
640 
641 	ret = ENOMEM;
642 	/*
643 	 * 1) get the config information to generate the ring to service
644 	 *    mapping table
645 	 * 2) init each bundle of this device
646 	 */
647 	for (i = 0; i < device->bundle_num; i++) {
648 		device->bundles[i] = malloc(sizeof(struct adf_cfg_bundle),
649 					    M_QAT,
650 					    M_WAITOK | M_ZERO);
651 
652 		device->bundles[i]->max_section = max_inst;
653 		adf_cfg_bundle_init(device->bundles[i], device, i, accel_dev);
654 	}
655 
656 	return 0;
657 
658 failed:
659 	for (i = 0; i < device->bundle_num; i++) {
660 		if (device->bundles[i])
661 			adf_cfg_bundle_clear(device->bundles[i], accel_dev);
662 	}
663 
664 	for (i = 0; i < (device->bundle_num * max_inst); i++) {
665 		if (device->instances && device->instances[i])
666 			free(device->instances[i], M_QAT);
667 	}
668 
669 	free(device->instances, M_QAT);
670 	device->instances = NULL;
671 
672 	device_printf(GET_DEV(accel_dev), "Failed to do device init\n");
673 	return ret;
674 }
675 
676 void
677 adf_cfg_device_clear(struct adf_cfg_device *device,
678 		     struct adf_accel_dev *accel_dev)
679 {
680 	int i = 0;
681 
682 	for (i = 0; i < device->bundle_num; i++) {
683 		if (device->bundles && device->bundles[i]) {
684 			adf_cfg_bundle_clear(device->bundles[i], accel_dev);
685 			free(device->bundles[i], M_QAT);
686 			device->bundles[i] = NULL;
687 		}
688 	}
689 
690 	free(device->bundles, M_QAT);
691 	device->bundles = NULL;
692 
693 	for (i = 0; i < device->instance_index; i++) {
694 		if (device->instances && device->instances[i]) {
695 			free(device->instances[i], M_QAT);
696 			device->instances[i] = NULL;
697 		}
698 	}
699 
700 	free(device->instances, M_QAT);
701 	device->instances = NULL;
702 }
703 
704 static int
705 adf_cfg_static_conf(struct adf_accel_dev *accel_dev)
706 {
707 	int ret = 0;
708 	unsigned long val = 0;
709 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
710 	char value[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
711 	int cpus;
712 	int instances = 0;
713 	int cy_poll_instances;
714 	int cy_irq_instances;
715 	int dc_instances;
716 	int i = 0;
717 
718 	cpus = num_online_cpus();
719 	instances =
720 	    GET_MAX_BANKS(accel_dev) > cpus ? GET_MAX_BANKS(accel_dev) : cpus;
721 	if (!instances)
722 		return EFAULT;
723 
724 	if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_DC)
725 		dc_instances = ADF_CFG_STATIC_CONF_INST_NUM_DC;
726 	else
727 		return EFAULT;
728 	instances -= dc_instances;
729 
730 	if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_CY_POLL)
731 		cy_poll_instances = ADF_CFG_STATIC_CONF_INST_NUM_CY_POLL;
732 	else
733 		return EFAULT;
734 	instances -= cy_poll_instances;
735 
736 	if (instances >= ADF_CFG_STATIC_CONF_INST_NUM_CY_IRQ)
737 		cy_irq_instances = ADF_CFG_STATIC_CONF_INST_NUM_CY_IRQ;
738 	else
739 		return EFAULT;
740 	instances -= cy_irq_instances;
741 
742 	ret |= adf_cfg_section_add(accel_dev, ADF_GENERAL_SEC);
743 
744 	ret |= adf_cfg_section_add(accel_dev, ADF_KERNEL_SAL_SEC);
745 
746 	val = ADF_CFG_STATIC_CONF_VER;
747 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CONFIG_VERSION);
748 	ret |= adf_cfg_add_key_value_param(
749 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
750 
751 	val = ADF_CFG_STATIC_CONF_AUTO_RESET;
752 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_AUTO_RESET_ON_ERROR);
753 	ret |= adf_cfg_add_key_value_param(
754 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
755 
756 	if (accel_dev->hw_device->get_num_accel_units) {
757 		int cy_au = 0;
758 		int dc_au = 0;
759 		int num_au = accel_dev->hw_device->get_num_accel_units(
760 		    accel_dev->hw_device);
761 
762 		if (num_au > ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS) {
763 			cy_au = num_au - ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS;
764 			dc_au = ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS;
765 		} else if (num_au == ADF_CFG_STATIC_CONF_NUM_DC_ACCEL_UNITS) {
766 			cy_au = 1;
767 			dc_au = 1;
768 		} else {
769 			return EFAULT;
770 		}
771 
772 		val = cy_au;
773 		snprintf(key,
774 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
775 			 ADF_NUM_CY_ACCEL_UNITS);
776 		ret |= adf_cfg_add_key_value_param(
777 		    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
778 
779 		val = dc_au;
780 		snprintf(key,
781 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
782 			 ADF_NUM_DC_ACCEL_UNITS);
783 		ret |= adf_cfg_add_key_value_param(
784 		    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
785 
786 		val = ADF_CFG_STATIC_CONF_NUM_INLINE_ACCEL_UNITS;
787 		snprintf(key,
788 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
789 			 ADF_NUM_INLINE_ACCEL_UNITS);
790 		ret |= adf_cfg_add_key_value_param(
791 		    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
792 	}
793 
794 	val = ADF_CFG_STATIC_CONF_CY_ASYM_RING_SIZE;
795 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CY ADF_RING_ASYM_SIZE);
796 	ret |= adf_cfg_add_key_value_param(
797 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
798 
799 	val = ADF_CFG_STATIC_CONF_CY_SYM_RING_SIZE;
800 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_CY ADF_RING_SYM_SIZE);
801 	ret |= adf_cfg_add_key_value_param(
802 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
803 
804 	val = ADF_CFG_STATIC_CONF_DC_INTER_BUF_SIZE;
805 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_INTER_BUF_SIZE);
806 	ret |= adf_cfg_add_key_value_param(
807 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
808 
809 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_SERVICES_ENABLED);
810 	if ((cy_poll_instances + cy_irq_instances) == 0 && dc_instances > 0) {
811 		snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CFG_DC);
812 	} else if (((cy_poll_instances + cy_irq_instances)) > 0 &&
813 		   dc_instances == 0) {
814 		snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CFG_SYM);
815 	} else {
816 		snprintf(value,
817 			 ADF_CFG_MAX_VAL_LEN_IN_BYTES,
818 			 "%s;%s",
819 			 ADF_CFG_SYM,
820 			 ADF_CFG_DC);
821 	}
822 	ret |= adf_cfg_add_key_value_param(
823 	    accel_dev, ADF_GENERAL_SEC, key, (void *)value, ADF_STR);
824 
825 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DC;
826 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DC);
827 	ret |= adf_cfg_add_key_value_param(
828 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
829 
830 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DH;
831 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DH);
832 	ret |= adf_cfg_add_key_value_param(
833 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
834 
835 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DRBG;
836 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DRBG);
837 	ret |= adf_cfg_add_key_value_param(
838 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
839 
840 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_DSA;
841 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_DSA);
842 	ret |= adf_cfg_add_key_value_param(
843 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
844 
845 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_ECC;
846 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_ECC);
847 	ret |= adf_cfg_add_key_value_param(
848 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
849 
850 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_ENABLED;
851 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_ENABLED);
852 	ret |= adf_cfg_add_key_value_param(
853 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
854 
855 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_KEYGEN;
856 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_KEYGEN);
857 	ret |= adf_cfg_add_key_value_param(
858 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
859 
860 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_LN;
861 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_LN);
862 	ret |= adf_cfg_add_key_value_param(
863 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
864 
865 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_PRIME;
866 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_PRIME);
867 	ret |= adf_cfg_add_key_value_param(
868 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
869 
870 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_RSA;
871 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_RSA);
872 	ret |= adf_cfg_add_key_value_param(
873 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
874 
875 	val = ADF_CFG_STATIC_CONF_SAL_STATS_CFG_SYM;
876 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, SAL_STATS_CFG_SYM);
877 	ret |= adf_cfg_add_key_value_param(
878 	    accel_dev, ADF_GENERAL_SEC, key, (void *)&val, ADF_DEC);
879 
880 	val = (cy_poll_instances + cy_irq_instances);
881 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_NUM_CY);
882 	ret |= adf_cfg_add_key_value_param(
883 	    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
884 
885 	val = dc_instances;
886 	snprintf(key, ADF_CFG_MAX_KEY_LEN_IN_BYTES, ADF_NUM_DC);
887 	ret |= adf_cfg_add_key_value_param(
888 	    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
889 
890 	for (i = 0; i < (cy_irq_instances); i++) {
891 		val = i;
892 		snprintf(key,
893 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
894 			 ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY,
895 			 i);
896 		ret |= adf_cfg_add_key_value_param(
897 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
898 
899 		val = ADF_CFG_STATIC_CONF_IRQ;
900 		snprintf(key,
901 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
902 			 ADF_CY "%d" ADF_POLL_MODE,
903 			 i);
904 		ret |= adf_cfg_add_key_value_param(
905 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
906 
907 		snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CY "%d", i);
908 		snprintf(key,
909 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
910 			 ADF_CY_NAME_FORMAT,
911 			 i);
912 		ret |= adf_cfg_add_key_value_param(
913 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR);
914 	}
915 
916 	for (i = cy_irq_instances; i < (cy_poll_instances + cy_irq_instances);
917 	     i++) {
918 		val = i;
919 		snprintf(key,
920 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
921 			 ADF_CY "%d" ADF_ETRMGR_CORE_AFFINITY,
922 			 i);
923 		ret |= adf_cfg_add_key_value_param(
924 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
925 
926 		val = ADF_CFG_STATIC_CONF_POLL;
927 		snprintf(key,
928 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
929 			 ADF_CY "%d" ADF_POLL_MODE,
930 			 i);
931 		ret |= adf_cfg_add_key_value_param(
932 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
933 
934 		snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_CY "%d", i);
935 		snprintf(key,
936 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
937 			 ADF_CY_NAME_FORMAT,
938 			 i);
939 		ret |= adf_cfg_add_key_value_param(
940 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR);
941 	}
942 
943 	for (i = 0; i < dc_instances; i++) {
944 		val = i;
945 		snprintf(key,
946 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
947 			 ADF_DC "%d" ADF_ETRMGR_CORE_AFFINITY,
948 			 i);
949 		ret |= adf_cfg_add_key_value_param(
950 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
951 
952 		val = ADF_CFG_STATIC_CONF_POLL;
953 		snprintf(key,
954 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
955 			 ADF_DC "%d" ADF_POLL_MODE,
956 			 i);
957 		ret |= adf_cfg_add_key_value_param(
958 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)&val, ADF_DEC);
959 
960 		snprintf(value, ADF_CFG_MAX_VAL_LEN_IN_BYTES, ADF_DC "%d", i);
961 		snprintf(key,
962 			 ADF_CFG_MAX_KEY_LEN_IN_BYTES,
963 			 ADF_DC_NAME_FORMAT,
964 			 i);
965 		ret |= adf_cfg_add_key_value_param(
966 		    accel_dev, ADF_KERNEL_SAL_SEC, key, (void *)value, ADF_STR);
967 	}
968 
969 	if (ret)
970 		ret = EFAULT;
971 	return ret;
972 }
973 
974 int
975 adf_config_device(struct adf_accel_dev *accel_dev)
976 {
977 	struct adf_cfg_device_data *cfg = NULL;
978 	struct adf_cfg_device *cfg_device = NULL;
979 	struct adf_cfg_section *sec;
980 	struct list_head *list;
981 	int ret = ENOMEM;
982 
983 	if (!accel_dev)
984 		return ret;
985 
986 	ret = adf_cfg_static_conf(accel_dev);
987 	if (ret)
988 		goto failed;
989 
990 	cfg = accel_dev->cfg;
991 	cfg->dev = NULL;
992 	cfg_device = (struct adf_cfg_device *)malloc(sizeof(*cfg_device),
993 						     M_QAT,
994 						     M_WAITOK | M_ZERO);
995 
996 	ret = EFAULT;
997 
998 	if (adf_cfg_device_init(cfg_device, accel_dev))
999 		goto failed;
1000 
1001 	cfg->dev = cfg_device;
1002 
1003 	/* GENERAL and KERNEL section must be processed before others */
1004 	list_for_each(list, &cfg->sec_list)
1005 	{
1006 		sec = list_entry(list, struct adf_cfg_section, list);
1007 		if (!strcmp(sec->name, ADF_GENERAL_SEC)) {
1008 			ret = adf_cfg_process_section(accel_dev,
1009 						      sec->name,
1010 						      accel_dev->accel_id);
1011 			if (ret)
1012 				goto failed;
1013 			sec->processed = true;
1014 			break;
1015 		}
1016 	}
1017 
1018 	list_for_each(list, &cfg->sec_list)
1019 	{
1020 		sec = list_entry(list, struct adf_cfg_section, list);
1021 		if (!strcmp(sec->name, ADF_KERNEL_SEC)) {
1022 			ret = adf_cfg_process_section(accel_dev,
1023 						      sec->name,
1024 						      accel_dev->accel_id);
1025 			if (ret)
1026 				goto failed;
1027 			sec->processed = true;
1028 			break;
1029 		}
1030 	}
1031 
1032 	list_for_each(list, &cfg->sec_list)
1033 	{
1034 		sec = list_entry(list, struct adf_cfg_section, list);
1035 		if (!strcmp(sec->name, ADF_KERNEL_SAL_SEC)) {
1036 			ret = adf_cfg_process_section(accel_dev,
1037 						      sec->name,
1038 						      accel_dev->accel_id);
1039 			if (ret)
1040 				goto failed;
1041 			sec->processed = true;
1042 			break;
1043 		}
1044 	}
1045 
1046 	list_for_each(list, &cfg->sec_list)
1047 	{
1048 		sec = list_entry(list, struct adf_cfg_section, list);
1049 		/* avoid reprocessing one section */
1050 		if (!sec->processed && !sec->is_derived) {
1051 			ret = adf_cfg_process_section(accel_dev,
1052 						      sec->name,
1053 						      accel_dev->accel_id);
1054 			if (ret)
1055 				goto failed;
1056 			sec->processed = true;
1057 		}
1058 	}
1059 
1060 	/* newly added accel section */
1061 	ret = adf_cfg_process_section(accel_dev,
1062 				      ADF_ACCEL_SEC,
1063 				      accel_dev->accel_id);
1064 	if (ret)
1065 		goto failed;
1066 
1067 	/*
1068 	 * put item-remove task after item-process
1069 	 * because during process we may fetch values from those items
1070 	 */
1071 	list_for_each(list, &cfg->sec_list)
1072 	{
1073 		sec = list_entry(list, struct adf_cfg_section, list);
1074 		if (!sec->is_derived) {
1075 			ret = adf_cfg_cleanup_section(accel_dev,
1076 						      sec->name,
1077 						      accel_dev->accel_id);
1078 			if (ret)
1079 				goto failed;
1080 		}
1081 	}
1082 
1083 	ret = 0;
1084 	set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
1085 failed:
1086 	if (ret) {
1087 		if (cfg_device) {
1088 			adf_cfg_device_clear(cfg_device, accel_dev);
1089 			free(cfg_device, M_QAT);
1090 			cfg->dev = NULL;
1091 		}
1092 		adf_cfg_del_all(accel_dev);
1093 		device_printf(GET_DEV(accel_dev), "Failed to config device\n");
1094 	}
1095 
1096 	return ret;
1097 }
1098