1 /*
2   This file is provided under a dual BSD/GPLv2 license.  When using or
3   redistributing this file, you may do so under either license.
4 
5   GPL LICENSE SUMMARY
6   Copyright(c) 2014 Intel Corporation.
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of version 2 of the GNU General Public License as
9   published by the Free Software Foundation.
10 
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15 
16   Contact Information:
17   qat-linux@intel.com
18 
19   BSD LICENSE
20   Copyright(c) 2014 Intel Corporation.
21   Redistribution and use in source and binary forms, with or without
22   modification, are permitted provided that the following conditions
23   are met:
24 
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above copyright
28       notice, this list of conditions and the following disclaimer in
29       the documentation and/or other materials provided with the
30       distribution.
31     * Neither the name of Intel Corporation nor the names of its
32       contributors may be used to endorse or promote products derived
33       from this software without specific prior written permission.
34 
35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 */
47 #include <linux/mutex.h>
48 #include <linux/list.h>
49 #include <linux/bitops.h>
50 #include <linux/delay.h>
51 #include "adf_accel_devices.h"
52 #include "adf_cfg.h"
53 #include "adf_common_drv.h"
54 
55 static LIST_HEAD(service_table);
56 static DEFINE_MUTEX(service_lock);
57 
adf_service_add(struct service_hndl * service)58 static void adf_service_add(struct service_hndl *service)
59 {
60 	mutex_lock(&service_lock);
61 	list_add(&service->list, &service_table);
62 	mutex_unlock(&service_lock);
63 }
64 
adf_service_register(struct service_hndl * service)65 int adf_service_register(struct service_hndl *service)
66 {
67 	memset(service->init_status, 0, sizeof(service->init_status));
68 	memset(service->start_status, 0, sizeof(service->start_status));
69 	adf_service_add(service);
70 	return 0;
71 }
72 
adf_service_remove(struct service_hndl * service)73 static void adf_service_remove(struct service_hndl *service)
74 {
75 	mutex_lock(&service_lock);
76 	list_del(&service->list);
77 	mutex_unlock(&service_lock);
78 }
79 
adf_service_unregister(struct service_hndl * service)80 int adf_service_unregister(struct service_hndl *service)
81 {
82 	int i;
83 
84 	for (i = 0; i < ARRAY_SIZE(service->init_status); i++) {
85 		if (service->init_status[i] || service->start_status[i]) {
86 			pr_err("QAT: Could not remove active service\n");
87 			return -EFAULT;
88 		}
89 	}
90 	adf_service_remove(service);
91 	return 0;
92 }
93 
94 /**
95  * adf_dev_init() - Init data structures and services for the given accel device
96  * @accel_dev: Pointer to acceleration device.
97  *
98  * Initialize the ring data structures and the admin comms and arbitration
99  * services.
100  *
101  * Return: 0 on success, error code otherwise.
102  */
adf_dev_init(struct adf_accel_dev * accel_dev)103 int adf_dev_init(struct adf_accel_dev *accel_dev)
104 {
105 	struct service_hndl *service;
106 	struct list_head *list_itr;
107 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
108 
109 	if (!hw_data) {
110 		dev_err(&GET_DEV(accel_dev),
111 			"Failed to init device - hw_data not set\n");
112 		return -EFAULT;
113 	}
114 
115 	if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
116 		dev_err(&GET_DEV(accel_dev), "Device not configured\n");
117 		return -EFAULT;
118 	}
119 
120 	if (adf_init_etr_data(accel_dev)) {
121 		dev_err(&GET_DEV(accel_dev), "Failed initialize etr\n");
122 		return -EFAULT;
123 	}
124 
125 	if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
126 		dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n");
127 		return -EFAULT;
128 	}
129 
130 	if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
131 		dev_err(&GET_DEV(accel_dev), "Failed initialize hw arbiter\n");
132 		return -EFAULT;
133 	}
134 
135 	hw_data->enable_ints(accel_dev);
136 
137 	if (adf_ae_init(accel_dev)) {
138 		dev_err(&GET_DEV(accel_dev),
139 			"Failed to initialise Acceleration Engine\n");
140 		return -EFAULT;
141 	}
142 	set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
143 
144 	if (adf_ae_fw_load(accel_dev)) {
145 		dev_err(&GET_DEV(accel_dev),
146 			"Failed to load acceleration FW\n");
147 		return -EFAULT;
148 	}
149 	set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
150 
151 	if (hw_data->alloc_irq(accel_dev)) {
152 		dev_err(&GET_DEV(accel_dev), "Failed to allocate interrupts\n");
153 		return -EFAULT;
154 	}
155 	set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
156 
157 	/*
158 	 * Subservice initialisation is divided into two stages: init and start.
159 	 * This is to facilitate any ordering dependencies between services
160 	 * prior to starting any of the accelerators.
161 	 */
162 	list_for_each(list_itr, &service_table) {
163 		service = list_entry(list_itr, struct service_hndl, list);
164 		if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
165 			dev_err(&GET_DEV(accel_dev),
166 				"Failed to initialise service %s\n",
167 				service->name);
168 			return -EFAULT;
169 		}
170 		set_bit(accel_dev->accel_id, service->init_status);
171 	}
172 
173 	hw_data->enable_error_correction(accel_dev);
174 	hw_data->enable_vf2pf_comms(accel_dev);
175 
176 	return 0;
177 }
178 EXPORT_SYMBOL_GPL(adf_dev_init);
179 
180 /**
181  * adf_dev_start() - Start acceleration service for the given accel device
182  * @accel_dev:    Pointer to acceleration device.
183  *
184  * Function notifies all the registered services that the acceleration device
185  * is ready to be used.
186  * To be used by QAT device specific drivers.
187  *
188  * Return: 0 on success, error code otherwise.
189  */
adf_dev_start(struct adf_accel_dev * accel_dev)190 int adf_dev_start(struct adf_accel_dev *accel_dev)
191 {
192 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
193 	struct service_hndl *service;
194 	struct list_head *list_itr;
195 
196 	set_bit(ADF_STATUS_STARTING, &accel_dev->status);
197 
198 	if (adf_ae_start(accel_dev)) {
199 		dev_err(&GET_DEV(accel_dev), "AE Start Failed\n");
200 		return -EFAULT;
201 	}
202 	set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
203 
204 	if (hw_data->send_admin_init(accel_dev)) {
205 		dev_err(&GET_DEV(accel_dev), "Failed to send init message\n");
206 		return -EFAULT;
207 	}
208 
209 	list_for_each(list_itr, &service_table) {
210 		service = list_entry(list_itr, struct service_hndl, list);
211 		if (service->event_hld(accel_dev, ADF_EVENT_START)) {
212 			dev_err(&GET_DEV(accel_dev),
213 				"Failed to start service %s\n",
214 				service->name);
215 			return -EFAULT;
216 		}
217 		set_bit(accel_dev->accel_id, service->start_status);
218 	}
219 
220 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
221 	set_bit(ADF_STATUS_STARTED, &accel_dev->status);
222 
223 	if (!list_empty(&accel_dev->crypto_list) &&
224 	    (qat_algs_register() || qat_asym_algs_register())) {
225 		dev_err(&GET_DEV(accel_dev),
226 			"Failed to register crypto algs\n");
227 		set_bit(ADF_STATUS_STARTING, &accel_dev->status);
228 		clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
229 		return -EFAULT;
230 	}
231 	return 0;
232 }
233 EXPORT_SYMBOL_GPL(adf_dev_start);
234 
235 /**
236  * adf_dev_stop() - Stop acceleration service for the given accel device
237  * @accel_dev:    Pointer to acceleration device.
238  *
239  * Function notifies all the registered services that the acceleration device
240  * is shuting down.
241  * To be used by QAT device specific drivers.
242  *
243  * Return: void
244  */
adf_dev_stop(struct adf_accel_dev * accel_dev)245 void adf_dev_stop(struct adf_accel_dev *accel_dev)
246 {
247 	struct service_hndl *service;
248 	struct list_head *list_itr;
249 	bool wait = false;
250 	int ret;
251 
252 	if (!adf_dev_started(accel_dev) &&
253 	    !test_bit(ADF_STATUS_STARTING, &accel_dev->status))
254 		return;
255 
256 	clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
257 	clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
258 
259 	if (!list_empty(&accel_dev->crypto_list)) {
260 		qat_algs_unregister();
261 		qat_asym_algs_unregister();
262 	}
263 
264 	list_for_each(list_itr, &service_table) {
265 		service = list_entry(list_itr, struct service_hndl, list);
266 		if (!test_bit(accel_dev->accel_id, service->start_status))
267 			continue;
268 		ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
269 		if (!ret) {
270 			clear_bit(accel_dev->accel_id, service->start_status);
271 		} else if (ret == -EAGAIN) {
272 			wait = true;
273 			clear_bit(accel_dev->accel_id, service->start_status);
274 		}
275 	}
276 
277 	if (wait)
278 		msleep(100);
279 
280 	if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
281 		if (adf_ae_stop(accel_dev))
282 			dev_err(&GET_DEV(accel_dev), "failed to stop AE\n");
283 		else
284 			clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
285 	}
286 }
287 EXPORT_SYMBOL_GPL(adf_dev_stop);
288 
289 /**
290  * adf_dev_shutdown() - shutdown acceleration services and data strucutures
291  * @accel_dev: Pointer to acceleration device
292  *
293  * Cleanup the ring data structures and the admin comms and arbitration
294  * services.
295  */
adf_dev_shutdown(struct adf_accel_dev * accel_dev)296 void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
297 {
298 	struct adf_hw_device_data *hw_data = accel_dev->hw_device;
299 	struct service_hndl *service;
300 	struct list_head *list_itr;
301 
302 	if (!hw_data) {
303 		dev_err(&GET_DEV(accel_dev),
304 			"QAT: Failed to shutdown device - hw_data not set\n");
305 		return;
306 	}
307 
308 	if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
309 		adf_ae_fw_release(accel_dev);
310 		clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
311 	}
312 
313 	if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
314 		if (adf_ae_shutdown(accel_dev))
315 			dev_err(&GET_DEV(accel_dev),
316 				"Failed to shutdown Accel Engine\n");
317 		else
318 			clear_bit(ADF_STATUS_AE_INITIALISED,
319 				  &accel_dev->status);
320 	}
321 
322 	list_for_each(list_itr, &service_table) {
323 		service = list_entry(list_itr, struct service_hndl, list);
324 		if (!test_bit(accel_dev->accel_id, service->init_status))
325 			continue;
326 		if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
327 			dev_err(&GET_DEV(accel_dev),
328 				"Failed to shutdown service %s\n",
329 				service->name);
330 		else
331 			clear_bit(accel_dev->accel_id, service->init_status);
332 	}
333 
334 	hw_data->disable_iov(accel_dev);
335 
336 	if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
337 		hw_data->free_irq(accel_dev);
338 		clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
339 	}
340 
341 	/* Delete configuration only if not restarting */
342 	if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
343 		adf_cfg_del_all(accel_dev);
344 
345 	if (hw_data->exit_arb)
346 		hw_data->exit_arb(accel_dev);
347 
348 	if (hw_data->exit_admin_comms)
349 		hw_data->exit_admin_comms(accel_dev);
350 
351 	adf_cleanup_etr_data(accel_dev);
352 	adf_dev_restore(accel_dev);
353 }
354 EXPORT_SYMBOL_GPL(adf_dev_shutdown);
355 
adf_dev_restarting_notify(struct adf_accel_dev * accel_dev)356 int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
357 {
358 	struct service_hndl *service;
359 	struct list_head *list_itr;
360 
361 	list_for_each(list_itr, &service_table) {
362 		service = list_entry(list_itr, struct service_hndl, list);
363 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
364 			dev_err(&GET_DEV(accel_dev),
365 				"Failed to restart service %s.\n",
366 				service->name);
367 	}
368 	return 0;
369 }
370 
adf_dev_restarted_notify(struct adf_accel_dev * accel_dev)371 int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
372 {
373 	struct service_hndl *service;
374 	struct list_head *list_itr;
375 
376 	list_for_each(list_itr, &service_table) {
377 		service = list_entry(list_itr, struct service_hndl, list);
378 		if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
379 			dev_err(&GET_DEV(accel_dev),
380 				"Failed to restart service %s.\n",
381 				service->name);
382 	}
383 	return 0;
384 }
385