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