GNU Linux-libre 4.9-gnu1
[releases.git] / drivers / crypto / qat / qat_common / adf_init.c
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
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
65 int adf_service_register(struct service_hndl *service)
66 {
67         service->init_status = 0;
68         service->start_status = 0;
69         adf_service_add(service);
70         return 0;
71 }
72
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
80 int adf_service_unregister(struct service_hndl *service)
81 {
82         if (service->init_status || service->start_status) {
83                 pr_err("QAT: Could not remove active service\n");
84                 return -EFAULT;
85         }
86         adf_service_remove(service);
87         return 0;
88 }
89
90 /**
91  * adf_dev_init() - Init data structures and services for the given accel device
92  * @accel_dev: Pointer to acceleration device.
93  *
94  * Initialize the ring data structures and the admin comms and arbitration
95  * services.
96  *
97  * Return: 0 on success, error code otherwise.
98  */
99 int adf_dev_init(struct adf_accel_dev *accel_dev)
100 {
101         struct service_hndl *service;
102         struct list_head *list_itr;
103         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
104
105         if (!hw_data) {
106                 dev_err(&GET_DEV(accel_dev),
107                         "Failed to init device - hw_data not set\n");
108                 return -EFAULT;
109         }
110
111         if (!test_bit(ADF_STATUS_CONFIGURED, &accel_dev->status)) {
112                 dev_err(&GET_DEV(accel_dev), "Device not configured\n");
113                 return -EFAULT;
114         }
115
116         if (adf_init_etr_data(accel_dev)) {
117                 dev_err(&GET_DEV(accel_dev), "Failed initialize etr\n");
118                 return -EFAULT;
119         }
120
121         if (hw_data->init_admin_comms && hw_data->init_admin_comms(accel_dev)) {
122                 dev_err(&GET_DEV(accel_dev), "Failed initialize admin comms\n");
123                 return -EFAULT;
124         }
125
126         if (hw_data->init_arb && hw_data->init_arb(accel_dev)) {
127                 dev_err(&GET_DEV(accel_dev), "Failed initialize hw arbiter\n");
128                 return -EFAULT;
129         }
130
131         hw_data->enable_ints(accel_dev);
132
133         if (adf_ae_init(accel_dev)) {
134                 dev_err(&GET_DEV(accel_dev),
135                         "Failed to initialise Acceleration Engine\n");
136                 return -EFAULT;
137         }
138         set_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status);
139
140         if (adf_ae_fw_load(accel_dev)) {
141                 dev_err(&GET_DEV(accel_dev),
142                         "Failed to load acceleration FW\n");
143                 return -EFAULT;
144         }
145         set_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
146
147         if (hw_data->alloc_irq(accel_dev)) {
148                 dev_err(&GET_DEV(accel_dev), "Failed to allocate interrupts\n");
149                 return -EFAULT;
150         }
151         set_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
152
153         /*
154          * Subservice initialisation is divided into two stages: init and start.
155          * This is to facilitate any ordering dependencies between services
156          * prior to starting any of the accelerators.
157          */
158         list_for_each(list_itr, &service_table) {
159                 service = list_entry(list_itr, struct service_hndl, list);
160                 if (service->event_hld(accel_dev, ADF_EVENT_INIT)) {
161                         dev_err(&GET_DEV(accel_dev),
162                                 "Failed to initialise service %s\n",
163                                 service->name);
164                         return -EFAULT;
165                 }
166                 set_bit(accel_dev->accel_id, &service->init_status);
167         }
168
169         hw_data->enable_error_correction(accel_dev);
170         hw_data->enable_vf2pf_comms(accel_dev);
171
172         return 0;
173 }
174 EXPORT_SYMBOL_GPL(adf_dev_init);
175
176 /**
177  * adf_dev_start() - Start acceleration service for the given accel device
178  * @accel_dev:    Pointer to acceleration device.
179  *
180  * Function notifies all the registered services that the acceleration device
181  * is ready to be used.
182  * To be used by QAT device specific drivers.
183  *
184  * Return: 0 on success, error code otherwise.
185  */
186 int adf_dev_start(struct adf_accel_dev *accel_dev)
187 {
188         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
189         struct service_hndl *service;
190         struct list_head *list_itr;
191
192         set_bit(ADF_STATUS_STARTING, &accel_dev->status);
193
194         if (adf_ae_start(accel_dev)) {
195                 dev_err(&GET_DEV(accel_dev), "AE Start Failed\n");
196                 return -EFAULT;
197         }
198         set_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
199
200         if (hw_data->send_admin_init(accel_dev)) {
201                 dev_err(&GET_DEV(accel_dev), "Failed to send init message\n");
202                 return -EFAULT;
203         }
204
205         list_for_each(list_itr, &service_table) {
206                 service = list_entry(list_itr, struct service_hndl, list);
207                 if (service->event_hld(accel_dev, ADF_EVENT_START)) {
208                         dev_err(&GET_DEV(accel_dev),
209                                 "Failed to start service %s\n",
210                                 service->name);
211                         return -EFAULT;
212                 }
213                 set_bit(accel_dev->accel_id, &service->start_status);
214         }
215
216         clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
217         set_bit(ADF_STATUS_STARTED, &accel_dev->status);
218
219         if (!list_empty(&accel_dev->crypto_list) &&
220             (qat_algs_register() || qat_asym_algs_register())) {
221                 dev_err(&GET_DEV(accel_dev),
222                         "Failed to register crypto algs\n");
223                 set_bit(ADF_STATUS_STARTING, &accel_dev->status);
224                 clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
225                 return -EFAULT;
226         }
227         return 0;
228 }
229 EXPORT_SYMBOL_GPL(adf_dev_start);
230
231 /**
232  * adf_dev_stop() - Stop acceleration service for the given accel device
233  * @accel_dev:    Pointer to acceleration device.
234  *
235  * Function notifies all the registered services that the acceleration device
236  * is shuting down.
237  * To be used by QAT device specific drivers.
238  *
239  * Return: void
240  */
241 void adf_dev_stop(struct adf_accel_dev *accel_dev)
242 {
243         struct service_hndl *service;
244         struct list_head *list_itr;
245         bool wait = false;
246         int ret;
247
248         if (!adf_dev_started(accel_dev) &&
249             !test_bit(ADF_STATUS_STARTING, &accel_dev->status))
250                 return;
251
252         clear_bit(ADF_STATUS_STARTING, &accel_dev->status);
253         clear_bit(ADF_STATUS_STARTED, &accel_dev->status);
254
255         if (!list_empty(&accel_dev->crypto_list)) {
256                 qat_algs_unregister();
257                 qat_asym_algs_unregister();
258         }
259
260         list_for_each(list_itr, &service_table) {
261                 service = list_entry(list_itr, struct service_hndl, list);
262                 if (!test_bit(accel_dev->accel_id, &service->start_status))
263                         continue;
264                 ret = service->event_hld(accel_dev, ADF_EVENT_STOP);
265                 if (!ret) {
266                         clear_bit(accel_dev->accel_id, &service->start_status);
267                 } else if (ret == -EAGAIN) {
268                         wait = true;
269                         clear_bit(accel_dev->accel_id, &service->start_status);
270                 }
271         }
272
273         if (wait)
274                 msleep(100);
275
276         if (test_bit(ADF_STATUS_AE_STARTED, &accel_dev->status)) {
277                 if (adf_ae_stop(accel_dev))
278                         dev_err(&GET_DEV(accel_dev), "failed to stop AE\n");
279                 else
280                         clear_bit(ADF_STATUS_AE_STARTED, &accel_dev->status);
281         }
282 }
283 EXPORT_SYMBOL_GPL(adf_dev_stop);
284
285 /**
286  * adf_dev_shutdown() - shutdown acceleration services and data strucutures
287  * @accel_dev: Pointer to acceleration device
288  *
289  * Cleanup the ring data structures and the admin comms and arbitration
290  * services.
291  */
292 void adf_dev_shutdown(struct adf_accel_dev *accel_dev)
293 {
294         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
295         struct service_hndl *service;
296         struct list_head *list_itr;
297
298         if (!hw_data) {
299                 dev_err(&GET_DEV(accel_dev),
300                         "QAT: Failed to shutdown device - hw_data not set\n");
301                 return;
302         }
303
304         if (test_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status)) {
305                 adf_ae_fw_release(accel_dev);
306                 clear_bit(ADF_STATUS_AE_UCODE_LOADED, &accel_dev->status);
307         }
308
309         if (test_bit(ADF_STATUS_AE_INITIALISED, &accel_dev->status)) {
310                 if (adf_ae_shutdown(accel_dev))
311                         dev_err(&GET_DEV(accel_dev),
312                                 "Failed to shutdown Accel Engine\n");
313                 else
314                         clear_bit(ADF_STATUS_AE_INITIALISED,
315                                   &accel_dev->status);
316         }
317
318         list_for_each(list_itr, &service_table) {
319                 service = list_entry(list_itr, struct service_hndl, list);
320                 if (!test_bit(accel_dev->accel_id, &service->init_status))
321                         continue;
322                 if (service->event_hld(accel_dev, ADF_EVENT_SHUTDOWN))
323                         dev_err(&GET_DEV(accel_dev),
324                                 "Failed to shutdown service %s\n",
325                                 service->name);
326                 else
327                         clear_bit(accel_dev->accel_id, &service->init_status);
328         }
329
330         hw_data->disable_iov(accel_dev);
331
332         if (test_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status)) {
333                 hw_data->free_irq(accel_dev);
334                 clear_bit(ADF_STATUS_IRQ_ALLOCATED, &accel_dev->status);
335         }
336
337         /* Delete configuration only if not restarting */
338         if (!test_bit(ADF_STATUS_RESTARTING, &accel_dev->status))
339                 adf_cfg_del_all(accel_dev);
340
341         if (hw_data->exit_arb)
342                 hw_data->exit_arb(accel_dev);
343
344         if (hw_data->exit_admin_comms)
345                 hw_data->exit_admin_comms(accel_dev);
346
347         adf_cleanup_etr_data(accel_dev);
348         adf_dev_restore(accel_dev);
349 }
350 EXPORT_SYMBOL_GPL(adf_dev_shutdown);
351
352 int adf_dev_restarting_notify(struct adf_accel_dev *accel_dev)
353 {
354         struct service_hndl *service;
355         struct list_head *list_itr;
356
357         list_for_each(list_itr, &service_table) {
358                 service = list_entry(list_itr, struct service_hndl, list);
359                 if (service->event_hld(accel_dev, ADF_EVENT_RESTARTING))
360                         dev_err(&GET_DEV(accel_dev),
361                                 "Failed to restart service %s.\n",
362                                 service->name);
363         }
364         return 0;
365 }
366
367 int adf_dev_restarted_notify(struct adf_accel_dev *accel_dev)
368 {
369         struct service_hndl *service;
370         struct list_head *list_itr;
371
372         list_for_each(list_itr, &service_table) {
373                 service = list_entry(list_itr, struct service_hndl, list);
374                 if (service->event_hld(accel_dev, ADF_EVENT_RESTARTED))
375                         dev_err(&GET_DEV(accel_dev),
376                                 "Failed to restart service %s.\n",
377                                 service->name);
378         }
379         return 0;
380 }