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