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