xref: /OK3568_Linux_fs/kernel/drivers/crypto/qat/qat_common/adf_init.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2*4882a593Smuzhiyun /* Copyright(c) 2014 - 2020 Intel Corporation */
3*4882a593Smuzhiyun #include <linux/mutex.h>
4*4882a593Smuzhiyun #include <linux/list.h>
5*4882a593Smuzhiyun #include <linux/bitops.h>
6*4882a593Smuzhiyun #include <linux/delay.h>
7*4882a593Smuzhiyun #include "adf_accel_devices.h"
8*4882a593Smuzhiyun #include "adf_cfg.h"
9*4882a593Smuzhiyun #include "adf_common_drv.h"
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun static LIST_HEAD(service_table);
12*4882a593Smuzhiyun static DEFINE_MUTEX(service_lock);
13*4882a593Smuzhiyun 
adf_service_add(struct service_hndl * service)14*4882a593Smuzhiyun static void adf_service_add(struct service_hndl *service)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun 	mutex_lock(&service_lock);
17*4882a593Smuzhiyun 	list_add(&service->list, &service_table);
18*4882a593Smuzhiyun 	mutex_unlock(&service_lock);
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun 
adf_service_register(struct service_hndl * service)21*4882a593Smuzhiyun int adf_service_register(struct service_hndl *service)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun 	memset(service->init_status, 0, sizeof(service->init_status));
24*4882a593Smuzhiyun 	memset(service->start_status, 0, sizeof(service->start_status));
25*4882a593Smuzhiyun 	adf_service_add(service);
26*4882a593Smuzhiyun 	return 0;
27*4882a593Smuzhiyun }
28*4882a593Smuzhiyun 
adf_service_remove(struct service_hndl * service)29*4882a593Smuzhiyun static void adf_service_remove(struct service_hndl *service)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	mutex_lock(&service_lock);
32*4882a593Smuzhiyun 	list_del(&service->list);
33*4882a593Smuzhiyun 	mutex_unlock(&service_lock);
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
adf_service_unregister(struct service_hndl * service)36*4882a593Smuzhiyun int adf_service_unregister(struct service_hndl *service)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	int i;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(service->init_status); i++) {
41*4882a593Smuzhiyun 		if (service->init_status[i] || service->start_status[i]) {
42*4882a593Smuzhiyun 			pr_err("QAT: Could not remove active service\n");
43*4882a593Smuzhiyun 			return -EFAULT;
44*4882a593Smuzhiyun 		}
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun 	adf_service_remove(service);
47*4882a593Smuzhiyun 	return 0;
48*4882a593Smuzhiyun }
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /**
51*4882a593Smuzhiyun  * adf_dev_init() - Init data structures and services for the given accel device
52*4882a593Smuzhiyun  * @accel_dev: Pointer to acceleration device.
53*4882a593Smuzhiyun  *
54*4882a593Smuzhiyun  * Initialize the ring data structures and the admin comms and arbitration
55*4882a593Smuzhiyun  * services.
56*4882a593Smuzhiyun  *
57*4882a593Smuzhiyun  * Return: 0 on success, error code otherwise.
58*4882a593Smuzhiyun  */
adf_dev_init(struct adf_accel_dev * accel_dev)59*4882a593Smuzhiyun int adf_dev_init(struct adf_accel_dev *accel_dev)
60*4882a593Smuzhiyun {
61*4882a593Smuzhiyun 	struct service_hndl *service;
62*4882a593Smuzhiyun 	struct list_head *list_itr;
63*4882a593Smuzhiyun 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
64*4882a593Smuzhiyun 	int ret;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	if (!hw_data) {
67*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev),
68*4882a593Smuzhiyun 			"Failed to init device - hw_data not set\n");
69*4882a593Smuzhiyun 		return -EFAULT;
70*4882a593Smuzhiyun 	}
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
73*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Device not configured\n");
74*4882a593Smuzhiyun 		return -EFAULT;
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (adf_init_etr_data(accel_dev)) {
78*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Failed initialize etr\n");
79*4882a593Smuzhiyun 		return -EFAULT;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
83*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n");
84*4882a593Smuzhiyun 		return -EFAULT;
85*4882a593Smuzhiyun 	}
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
88*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Failed initialize hw arbiter\n");
89*4882a593Smuzhiyun 		return -EFAULT;
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	hw_data->enable_ints(accel_dev);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	if (adf_ae_init(accel_dev)) {
95*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev),
96*4882a593Smuzhiyun 			"Failed to initialise Acceleration Engine\n");
97*4882a593Smuzhiyun 		return -EFAULT;
98*4882a593Smuzhiyun 	}
99*4882a593Smuzhiyun 	set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (adf_ae_fw_load(accel_dev)) {
102*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev),
103*4882a593Smuzhiyun 			"Failed to load acceleration FW\n");
104*4882a593Smuzhiyun 		return -EFAULT;
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun 	set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (hw_data->alloc_irq(accel_dev)) {
109*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Failed to allocate interrupts\n");
110*4882a593Smuzhiyun 		return -EFAULT;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/*
115*4882a593Smuzhiyun 	 * Subservice initialisation is divided into two stages: init and start.
116*4882a593Smuzhiyun 	 * This is to facilitate any ordering dependencies between services
117*4882a593Smuzhiyun 	 * prior to starting any of the accelerators.
118*4882a593Smuzhiyun 	 */
119*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
120*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
121*4882a593Smuzhiyun 		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
122*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
123*4882a593Smuzhiyun 				"Failed to initialise service %s\n",
124*4882a593Smuzhiyun 				service->name);
125*4882a593Smuzhiyun 			return -EFAULT;
126*4882a593Smuzhiyun 		}
127*4882a593Smuzhiyun 		set_bit(accel_dev->accel_id, service->init_status);
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	hw_data->enable_error_correction(accel_dev);
131*4882a593Smuzhiyun 	ret = hw_data->enable_vf2pf_comms(accel_dev);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	return ret;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_dev_init);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun /**
138*4882a593Smuzhiyun  * adf_dev_start() - Start acceleration service for the given accel device
139*4882a593Smuzhiyun  * @accel_dev:    Pointer to acceleration device.
140*4882a593Smuzhiyun  *
141*4882a593Smuzhiyun  * Function notifies all the registered services that the acceleration device
142*4882a593Smuzhiyun  * is ready to be used.
143*4882a593Smuzhiyun  * To be used by QAT device specific drivers.
144*4882a593Smuzhiyun  *
145*4882a593Smuzhiyun  * Return: 0 on success, error code otherwise.
146*4882a593Smuzhiyun  */
adf_dev_start(struct adf_accel_dev * accel_dev)147*4882a593Smuzhiyun int adf_dev_start(struct adf_accel_dev *accel_dev)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
150*4882a593Smuzhiyun 	struct service_hndl *service;
151*4882a593Smuzhiyun 	struct list_head *list_itr;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	set_bit(ADF_STATUS_STARTING, &accel_dev->status);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	if (adf_ae_start(accel_dev)) {
156*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "AE Start Failed\n");
157*4882a593Smuzhiyun 		return -EFAULT;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 	set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	if (hw_data->send_admin_init(accel_dev)) {
162*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev), "Failed to send init message\n");
163*4882a593Smuzhiyun 		return -EFAULT;
164*4882a593Smuzhiyun 	}
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
167*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
168*4882a593Smuzhiyun 		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
169*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
170*4882a593Smuzhiyun 				"Failed to start service %s\n",
171*4882a593Smuzhiyun 				service->name);
172*4882a593Smuzhiyun 			return -EFAULT;
173*4882a593Smuzhiyun 		}
174*4882a593Smuzhiyun 		set_bit(accel_dev->accel_id, service->start_status);
175*4882a593Smuzhiyun 	}
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
178*4882a593Smuzhiyun 	set_bit(ADF_STATUS_STARTED, &accel_dev->status);
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	if (!list_empty(&accel_dev->crypto_list) &&
181*4882a593Smuzhiyun 	    (qat_algs_register() || qat_asym_algs_register())) {
182*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev),
183*4882a593Smuzhiyun 			"Failed to register crypto algs\n");
184*4882a593Smuzhiyun 		set_bit(ADF_STATUS_STARTING, &accel_dev->status);
185*4882a593Smuzhiyun 		clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
186*4882a593Smuzhiyun 		return -EFAULT;
187*4882a593Smuzhiyun 	}
188*4882a593Smuzhiyun 	return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_dev_start);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun /**
193*4882a593Smuzhiyun  * adf_dev_stop() - Stop acceleration service for the given accel device
194*4882a593Smuzhiyun  * @accel_dev:    Pointer to acceleration device.
195*4882a593Smuzhiyun  *
196*4882a593Smuzhiyun  * Function notifies all the registered services that the acceleration device
197*4882a593Smuzhiyun  * is shuting down.
198*4882a593Smuzhiyun  * To be used by QAT device specific drivers.
199*4882a593Smuzhiyun  *
200*4882a593Smuzhiyun  * Return: void
201*4882a593Smuzhiyun  */
adf_dev_stop(struct adf_accel_dev * accel_dev)202*4882a593Smuzhiyun void adf_dev_stop(struct adf_accel_dev *accel_dev)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	struct service_hndl *service;
205*4882a593Smuzhiyun 	struct list_head *list_itr;
206*4882a593Smuzhiyun 	bool wait = false;
207*4882a593Smuzhiyun 	int ret;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	if (!adf_dev_started(accel_dev) &&
210*4882a593Smuzhiyun 	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status))
211*4882a593Smuzhiyun 		return;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
214*4882a593Smuzhiyun 	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	if (!list_empty(&accel_dev->crypto_list)) {
217*4882a593Smuzhiyun 		qat_algs_unregister();
218*4882a593Smuzhiyun 		qat_asym_algs_unregister();
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
222*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
223*4882a593Smuzhiyun 		if (!test_bit(accel_dev->accel_id, service->start_status))
224*4882a593Smuzhiyun 			continue;
225*4882a593Smuzhiyun 		ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
226*4882a593Smuzhiyun 		if (!ret) {
227*4882a593Smuzhiyun 			clear_bit(accel_dev->accel_id, service->start_status);
228*4882a593Smuzhiyun 		} else if (ret == -EAGAIN) {
229*4882a593Smuzhiyun 			wait = true;
230*4882a593Smuzhiyun 			clear_bit(accel_dev->accel_id, service->start_status);
231*4882a593Smuzhiyun 		}
232*4882a593Smuzhiyun 	}
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (wait)
235*4882a593Smuzhiyun 		msleep(100);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
238*4882a593Smuzhiyun 		if (adf_ae_stop(accel_dev))
239*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev), "failed to stop AE\n");
240*4882a593Smuzhiyun 		else
241*4882a593Smuzhiyun 			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
242*4882a593Smuzhiyun 	}
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_dev_stop);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun /**
247*4882a593Smuzhiyun  * adf_dev_shutdown() - shutdown acceleration services and data strucutures
248*4882a593Smuzhiyun  * @accel_dev: Pointer to acceleration device
249*4882a593Smuzhiyun  *
250*4882a593Smuzhiyun  * Cleanup the ring data structures and the admin comms and arbitration
251*4882a593Smuzhiyun  * services.
252*4882a593Smuzhiyun  */
adf_dev_shutdown(struct adf_accel_dev * accel_dev)253*4882a593Smuzhiyun void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
256*4882a593Smuzhiyun 	struct service_hndl *service;
257*4882a593Smuzhiyun 	struct list_head *list_itr;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	if (!hw_data) {
260*4882a593Smuzhiyun 		dev_err(&GET_DEV(accel_dev),
261*4882a593Smuzhiyun 			"QAT: Failed to shutdown device - hw_data not set\n");
262*4882a593Smuzhiyun 		return;
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
266*4882a593Smuzhiyun 		adf_ae_fw_release(accel_dev);
267*4882a593Smuzhiyun 		clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
268*4882a593Smuzhiyun 	}
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
271*4882a593Smuzhiyun 		if (adf_ae_shutdown(accel_dev))
272*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
273*4882a593Smuzhiyun 				"Failed to shutdown Accel Engine\n");
274*4882a593Smuzhiyun 		else
275*4882a593Smuzhiyun 			clear_bit(ADF_STATUS_AE_INITIALISED,
276*4882a593Smuzhiyun 				  &accel_dev->status);
277*4882a593Smuzhiyun 	}
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
280*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
281*4882a593Smuzhiyun 		if (!test_bit(accel_dev->accel_id, service->init_status))
282*4882a593Smuzhiyun 			continue;
283*4882a593Smuzhiyun 		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
284*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
285*4882a593Smuzhiyun 				"Failed to shutdown service %s\n",
286*4882a593Smuzhiyun 				service->name);
287*4882a593Smuzhiyun 		else
288*4882a593Smuzhiyun 			clear_bit(accel_dev->accel_id, service->init_status);
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	hw_data->disable_iov(accel_dev);
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
294*4882a593Smuzhiyun 		hw_data->free_irq(accel_dev);
295*4882a593Smuzhiyun 		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	/* Delete configuration only if not restarting */
299*4882a593Smuzhiyun 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
300*4882a593Smuzhiyun 		adf_cfg_del_all(accel_dev);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (hw_data->exit_arb)
303*4882a593Smuzhiyun 		hw_data->exit_arb(accel_dev);
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	if (hw_data->exit_admin_comms)
306*4882a593Smuzhiyun 		hw_data->exit_admin_comms(accel_dev);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	adf_cleanup_etr_data(accel_dev);
309*4882a593Smuzhiyun 	adf_dev_restore(accel_dev);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(adf_dev_shutdown);
312*4882a593Smuzhiyun 
adf_dev_restarting_notify(struct adf_accel_dev * accel_dev)313*4882a593Smuzhiyun int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	struct service_hndl *service;
316*4882a593Smuzhiyun 	struct list_head *list_itr;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
319*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
320*4882a593Smuzhiyun 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
321*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
322*4882a593Smuzhiyun 				"Failed to restart service %s.\n",
323*4882a593Smuzhiyun 				service->name);
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 	return 0;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
adf_dev_restarted_notify(struct adf_accel_dev * accel_dev)328*4882a593Smuzhiyun int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun 	struct service_hndl *service;
331*4882a593Smuzhiyun 	struct list_head *list_itr;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	list_for_each(list_itr, &service_table) {
334*4882a593Smuzhiyun 		service = list_entry(list_itr, struct service_hndl, list);
335*4882a593Smuzhiyun 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
336*4882a593Smuzhiyun 			dev_err(&GET_DEV(accel_dev),
337*4882a593Smuzhiyun 				"Failed to restart service %s.\n",
338*4882a593Smuzhiyun 				service->name);
339*4882a593Smuzhiyun 	}
340*4882a593Smuzhiyun 	return 0;
341*4882a593Smuzhiyun }
342