1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 #include "adf_cfg.h"
4 #include "cpa.h"
5 #include "icp_accel_devices.h"
6 #include "adf_common_drv.h"
7 #include "icp_adf_accel_mgr.h"
8 #include "icp_adf_cfg.h"
9 #include "icp_adf_debug.h"
10 #include "icp_adf_init.h"
11 #include "lac_sal_ctrl.h"
12 
13 static subservice_registation_handle_t *salService = NULL;
14 static struct service_hndl adfService = { 0 };
15 static icp_accel_dev_t *adfDevices = NULL;
16 static icp_accel_dev_t *adfDevicesHead = NULL;
17 struct mtx *adfDevicesLock;
18 
19 /*
20  * Need to keep track of what device is currently in reset state
21  */
22 static char accel_dev_reset_stat[ADF_MAX_DEVICES] = { 0 };
23 
24 /*
25  * Need to keep track of what device is currently in error state
26  */
27 static char accel_dev_error_stat[ADF_MAX_DEVICES] = { 0 };
28 
29 /*
30  * Need to preserve sal handle during restart
31  */
32 static void *accel_dev_sal_hdl_ptr[ADF_MAX_DEVICES] = { 0 };
33 
34 static icp_accel_dev_t *
35 create_adf_dev_structure(struct adf_accel_dev *accel_dev)
36 {
37 	icp_accel_dev_t *adf = NULL;
38 
39 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
40 
41 	adf = malloc(sizeof(*adf), M_QAT, M_WAITOK);
42 	memset(adf, 0, sizeof(*adf));
43 	adf->accelId = accel_dev->accel_id;
44 	adf->pAccelName = (char *)hw_data->dev_class->name;
45 	adf->deviceType = (device_type_t)hw_data->dev_class->type;
46 	strlcpy(adf->deviceName,
47 		hw_data->dev_class->name,
48 		sizeof(adf->deviceName));
49 	adf->accelCapabilitiesMask = hw_data->accel_capabilities_mask;
50 	adf->sku = hw_data->get_sku(hw_data);
51 	adf->accel_dev = accel_dev;
52 	accel_dev->lac_dev = adf;
53 
54 	return adf;
55 }
56 
57 /*
58  * adf_event_handler
59  * Handle device init/uninit/start/stop event
60  */
61 static CpaStatus
62 adf_event_handler(struct adf_accel_dev *accel_dev, enum adf_event event)
63 {
64 	CpaStatus status = CPA_STATUS_FAIL;
65 	icp_accel_dev_t *adf = NULL;
66 
67 	if (!adf_cfg_sec_find(accel_dev, ADF_KERNEL_SAL_SEC)) {
68 		return CPA_STATUS_SUCCESS;
69 	}
70 
71 	if (event == ADF_EVENT_INIT) {
72 		adf = create_adf_dev_structure(accel_dev);
73 		if (NULL == adf) {
74 			return CPA_STATUS_FAIL;
75 		}
76 		if (accel_dev_sal_hdl_ptr[accel_dev->accel_id]) {
77 			adf->pSalHandle =
78 			    accel_dev_sal_hdl_ptr[accel_dev->accel_id];
79 			accel_dev_sal_hdl_ptr[accel_dev->accel_id] = NULL;
80 		}
81 
82 		qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
83 		ICP_ADD_ELEMENT_TO_END_OF_LIST(adf, adfDevices, adfDevicesHead);
84 		qatUtilsMutexUnlock(&adfDevicesLock);
85 	} else {
86 		adf = accel_dev->lac_dev;
87 	}
88 
89 	if (event == ADF_EVENT_START) {
90 		adf->dcExtendedFeatures =
91 		    accel_dev->hw_device->extended_dc_capabilities;
92 	}
93 
94 	if (event == ADF_EVENT_RESTARTING) {
95 		accel_dev_reset_stat[accel_dev->accel_id] = 1;
96 		accel_dev_sal_hdl_ptr[accel_dev->accel_id] = adf->pSalHandle;
97 	}
98 
99 	if (event == ADF_EVENT_RESTARTED) {
100 		accel_dev_reset_stat[accel_dev->accel_id] = 0;
101 		accel_dev_error_stat[accel_dev->accel_id] = 0;
102 	}
103 
104 	status =
105 	    salService->subserviceEventHandler(adf,
106 					       (icp_adf_subsystemEvent_t)event,
107 					       NULL);
108 
109 	if (event == ADF_EVENT_ERROR) {
110 		accel_dev_error_stat[accel_dev->accel_id] = 1;
111 	}
112 
113 	if ((status == CPA_STATUS_SUCCESS && event == ADF_EVENT_SHUTDOWN) ||
114 	    (status != CPA_STATUS_SUCCESS && event == ADF_EVENT_INIT)) {
115 		qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
116 		ICP_REMOVE_ELEMENT_FROM_LIST(adf, adfDevices, adfDevicesHead);
117 		qatUtilsMutexUnlock(&adfDevicesLock);
118 		accel_dev->lac_dev = NULL;
119 		free(adf, M_QAT);
120 	}
121 
122 	if (status == CPA_STATUS_SUCCESS && event == ADF_EVENT_START) {
123 		qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
124 		adf->adfSubsystemStatus = 1;
125 		qatUtilsMutexUnlock(&adfDevicesLock);
126 	}
127 
128 	if ((status == CPA_STATUS_SUCCESS && event == ADF_EVENT_STOP) ||
129 	    (status == CPA_STATUS_RETRY && event == ADF_EVENT_STOP)) {
130 		qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
131 		adf->adfSubsystemStatus = 0;
132 		qatUtilsMutexUnlock(&adfDevicesLock);
133 		status = CPA_STATUS_SUCCESS;
134 	}
135 
136 	return status;
137 }
138 
139 /*
140  * icp_adf_subsystemRegister
141  * adapter function from SAL to adf driver
142  * call adf_service_register from adf driver directly with same
143  * parameters
144  */
145 CpaStatus
146 icp_adf_subsystemRegister(
147     subservice_registation_handle_t *sal_service_reg_handle)
148 {
149 	if (salService != NULL)
150 		return CPA_STATUS_FAIL;
151 
152 	salService = sal_service_reg_handle;
153 	adfService.name = sal_service_reg_handle->subsystem_name;
154 	adfService.event_hld = adf_event_handler;
155 
156 	if (adf_service_register(&adfService) == 0) {
157 		return CPA_STATUS_SUCCESS;
158 	} else {
159 		salService = NULL;
160 		return CPA_STATUS_FAIL;
161 	}
162 }
163 
164 /*
165  * icp_adf_subsystemUnegister
166  * adapter function from SAL to adf driver
167  */
168 CpaStatus
169 icp_adf_subsystemUnregister(
170     subservice_registation_handle_t *sal_service_reg_handle)
171 {
172 	if (adf_service_unregister(&adfService) == 0) {
173 		salService = NULL;
174 		return CPA_STATUS_SUCCESS;
175 	} else {
176 		return CPA_STATUS_FAIL;
177 	}
178 }
179 
180 /*
181  * icp_adf_cfgGetParamValue
182  * get parameter value from section @section with key @param
183  */
184 CpaStatus
185 icp_adf_cfgGetParamValue(icp_accel_dev_t *adf,
186 			 const char *section,
187 			 const char *param,
188 			 char *value)
189 {
190 	if (adf_cfg_get_param_value(adf->accel_dev, section, param, value) ==
191 	    0) {
192 		return CPA_STATUS_SUCCESS;
193 	} else {
194 		return CPA_STATUS_FAIL;
195 	}
196 }
197 
198 CpaBoolean
199 icp_adf_is_dev_in_reset(icp_accel_dev_t *accel_dev)
200 {
201 	return (CpaBoolean)accel_dev_reset_stat[accel_dev->accelId];
202 }
203 
204 CpaStatus
205 icp_adf_debugAddDir(icp_accel_dev_t *adf, debug_dir_info_t *dir_info)
206 {
207 	return CPA_STATUS_SUCCESS;
208 }
209 
210 void
211 icp_adf_debugRemoveDir(debug_dir_info_t *dir_info)
212 {
213 }
214 
215 CpaStatus
216 icp_adf_debugAddFile(icp_accel_dev_t *adf, debug_file_info_t *file_info)
217 {
218 	return CPA_STATUS_SUCCESS;
219 }
220 
221 void
222 icp_adf_debugRemoveFile(debug_file_info_t *file_info)
223 {
224 }
225 
226 /*
227  * icp_adf_getAccelDevByAccelId
228  * return acceleration device with id @accelId
229  */
230 icp_accel_dev_t *
231 icp_adf_getAccelDevByAccelId(Cpa32U accelId)
232 {
233 	icp_accel_dev_t *adf = NULL;
234 
235 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
236 	adf = adfDevicesHead;
237 	while (adf != NULL && adf->accelId != accelId)
238 		adf = adf->pNext;
239 	qatUtilsMutexUnlock(&adfDevicesLock);
240 	return adf;
241 }
242 
243 /*
244  * icp_amgr_getNumInstances
245  * Return the number of acceleration devices it the system.
246  */
247 CpaStatus
248 icp_amgr_getNumInstances(Cpa16U *pNumInstances)
249 {
250 	icp_accel_dev_t *adf = NULL;
251 	Cpa16U count = 0;
252 
253 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
254 	for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext)
255 		count++;
256 	qatUtilsMutexUnlock(&adfDevicesLock);
257 	*pNumInstances = count;
258 	return CPA_STATUS_SUCCESS;
259 }
260 
261 /*
262  * icp_amgr_getAccelDevByCapabilities
263  * Returns a started accel device that implements
264  * the capabilities specified in capabilitiesMask.
265  */
266 CpaStatus
267 icp_amgr_getAccelDevByCapabilities(Cpa32U capabilitiesMask,
268 				   icp_accel_dev_t **pAccel_devs,
269 				   Cpa16U *pNumInstances)
270 {
271 	icp_accel_dev_t *adf = NULL;
272 	*pNumInstances = 0;
273 
274 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
275 	for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) {
276 		if (adf->accelCapabilitiesMask & capabilitiesMask) {
277 			if (adf->adfSubsystemStatus) {
278 				pAccel_devs[0] = adf;
279 				*pNumInstances = 1;
280 				qatUtilsMutexUnlock(&adfDevicesLock);
281 				return CPA_STATUS_SUCCESS;
282 			}
283 		}
284 	}
285 	qatUtilsMutexUnlock(&adfDevicesLock);
286 	return CPA_STATUS_FAIL;
287 }
288 
289 /*
290  * icp_amgr_getAllAccelDevByEachCapabilities
291  * Returns table of accel devices that are started and implement
292  * each of the capabilities specified in capabilitiesMask.
293  */
294 CpaStatus
295 icp_amgr_getAllAccelDevByEachCapability(Cpa32U capabilitiesMask,
296 					icp_accel_dev_t **pAccel_devs,
297 					Cpa16U *pNumInstances)
298 {
299 	icp_accel_dev_t *adf = NULL;
300 	*pNumInstances = 0;
301 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
302 	for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) {
303 		Cpa32U enabled_caps =
304 		    adf->accelCapabilitiesMask & capabilitiesMask;
305 		if (enabled_caps == capabilitiesMask) {
306 			if (adf->adfSubsystemStatus) {
307 				pAccel_devs[(*pNumInstances)++] =
308 				    (icp_accel_dev_t *)adf;
309 			}
310 		}
311 	}
312 	qatUtilsMutexUnlock(&adfDevicesLock);
313 	return CPA_STATUS_SUCCESS;
314 }
315 
316 /*
317  * icp_amgr_getAllAccelDevByCapabilities
318  * Fetches accel devices based on the capability
319  * and returns the count of the device
320  */
321 CpaStatus
322 icp_amgr_getAllAccelDevByCapabilities(Cpa32U capabilitiesMask,
323 				      icp_accel_dev_t **pAccel_devs,
324 				      Cpa16U *pNumInstances)
325 {
326 	icp_accel_dev_t *adf = NULL;
327 	Cpa16U i = 0;
328 
329 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
330 	for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) {
331 		if (adf->accelCapabilitiesMask & capabilitiesMask) {
332 			if (adf->adfSubsystemStatus) {
333 				pAccel_devs[i++] = adf;
334 			}
335 		}
336 	}
337 	qatUtilsMutexUnlock(&adfDevicesLock);
338 	*pNumInstances = i;
339 	return CPA_STATUS_SUCCESS;
340 }
341 
342 /*
343  * icp_amgr_getAccelDevCapabilities
344  * Returns accel devices capabilities specified in capabilitiesMask.
345  *
346  * Returns:
347  *   CPA_STATUS_SUCCESS   on success
348  *   CPA_STATUS_FAIL      on failure
349  */
350 CpaStatus
351 icp_amgr_getAccelDevCapabilities(icp_accel_dev_t *accel_dev,
352 				 Cpa32U *pCapabilitiesMask)
353 {
354 	ICP_CHECK_FOR_NULL_PARAM(accel_dev);
355 	ICP_CHECK_FOR_NULL_PARAM(pCapabilitiesMask);
356 
357 	*pCapabilitiesMask = accel_dev->accelCapabilitiesMask;
358 	return CPA_STATUS_SUCCESS;
359 }
360 
361 /*
362  * icp_qa_dev_get
363  *
364  * Description:
365  * Function increments the device usage counter.
366  *
367  * Returns: void
368  */
369 void
370 icp_qa_dev_get(icp_accel_dev_t *pDev)
371 {
372 	ICP_CHECK_FOR_NULL_PARAM_VOID(pDev);
373 	adf_dev_get(pDev->accel_dev);
374 }
375 
376 /*
377  * icp_qa_dev_put
378  *
379  * Description:
380  * Function decrements the device usage counter.
381  *
382  * Returns: void
383  */
384 void
385 icp_qa_dev_put(icp_accel_dev_t *pDev)
386 {
387 	ICP_CHECK_FOR_NULL_PARAM_VOID(pDev);
388 	adf_dev_put(pDev->accel_dev);
389 }
390 
391 Cpa16U
392 icp_adf_get_busAddress(Cpa16U packageId)
393 {
394 	Cpa16U busAddr = 0xFFFF;
395 	icp_accel_dev_t *adf = NULL;
396 
397 	qatUtilsMutexLock(&adfDevicesLock, QAT_UTILS_WAIT_FOREVER);
398 	for (adf = adfDevicesHead; adf != NULL; adf = adf->pNext) {
399 		if (adf->accelId == packageId) {
400 			busAddr = pci_get_bus(accel_to_pci_dev(adf->accel_dev))
401 				<< 8 |
402 			    pci_get_slot(accel_to_pci_dev(adf->accel_dev))
403 				<< 3 |
404 			    pci_get_function(accel_to_pci_dev(adf->accel_dev));
405 			break;
406 		}
407 	}
408 	qatUtilsMutexUnlock(&adfDevicesLock);
409 	return busAddr;
410 }
411 
412 CpaBoolean
413 icp_adf_isSubsystemStarted(subservice_registation_handle_t *subsystem_hdl)
414 {
415 	if (subsystem_hdl == salService)
416 		return CPA_TRUE;
417 	else
418 		return CPA_FALSE;
419 }
420 
421 CpaBoolean
422 icp_adf_is_dev_in_error(icp_accel_dev_t *accel_dev)
423 {
424 	return (CpaBoolean)accel_dev_error_stat[accel_dev->accelId];
425 }
426