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
13static subservice_registation_handle_t *salService = NULL;
14static struct service_hndl adfService = { 0 };
15static icp_accel_dev_t *adfDevices = NULL;
16static icp_accel_dev_t *adfDevicesHead = NULL;
17struct mtx *adfDevicesLock;
18
19/*
20 * Need to keep track of what device is currently in reset state
21 */
22static 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 */
27static char accel_dev_error_stat[ADF_MAX_DEVICES] = { 0 };
28
29/*
30 * Need to preserve sal handle during restart
31 */
32static void *accel_dev_sal_hdl_ptr[ADF_MAX_DEVICES] = { 0 };
33
34static icp_accel_dev_t *
35create_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 */
61static CpaStatus
62adf_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 */
145CpaStatus
146icp_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 */
168CpaStatus
169icp_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 */
184CpaStatus
185icp_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
198CpaBoolean
199icp_adf_is_dev_in_reset(icp_accel_dev_t *accel_dev)
200{
201	return (CpaBoolean)accel_dev_reset_stat[accel_dev->accelId];
202}
203
204CpaStatus
205icp_adf_debugAddDir(icp_accel_dev_t *adf, debug_dir_info_t *dir_info)
206{
207	return CPA_STATUS_SUCCESS;
208}
209
210void
211icp_adf_debugRemoveDir(debug_dir_info_t *dir_info)
212{
213}
214
215CpaStatus
216icp_adf_debugAddFile(icp_accel_dev_t *adf, debug_file_info_t *file_info)
217{
218	return CPA_STATUS_SUCCESS;
219}
220
221void
222icp_adf_debugRemoveFile(debug_file_info_t *file_info)
223{
224}
225
226/*
227 * icp_adf_getAccelDevByAccelId
228 * return acceleration device with id @accelId
229 */
230icp_accel_dev_t *
231icp_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 */
247CpaStatus
248icp_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 */
266CpaStatus
267icp_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 */
294CpaStatus
295icp_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 */
321CpaStatus
322icp_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 */
350CpaStatus
351icp_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 */
369void
370icp_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 */
384void
385icp_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
391Cpa16U
392icp_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
412CpaBoolean
413icp_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
421CpaBoolean
422icp_adf_is_dev_in_error(icp_accel_dev_t *accel_dev)
423{
424	return (CpaBoolean)accel_dev_error_stat[accel_dev->accelId];
425}
426