]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/crypto/qat/qat_common/adf_ctl_drv.c
Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[mirror_ubuntu-jammy-kernel.git] / drivers / crypto / qat / qat_common / adf_ctl_drv.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/module.h>
48 #include <linux/mutex.h>
49 #include <linux/slab.h>
50 #include <linux/fs.h>
51 #include <linux/bitops.h>
52 #include <linux/pci.h>
53 #include <linux/cdev.h>
54 #include <linux/uaccess.h>
55
56 #include "adf_accel_devices.h"
57 #include "adf_common_drv.h"
58 #include "adf_cfg.h"
59 #include "adf_cfg_common.h"
60 #include "adf_cfg_user.h"
61
62 #define DEVICE_NAME "qat_adf_ctl"
63
64 static DEFINE_MUTEX(adf_ctl_lock);
65 static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg);
66
67 static const struct file_operations adf_ctl_ops = {
68 .owner = THIS_MODULE,
69 .unlocked_ioctl = adf_ctl_ioctl,
70 .compat_ioctl = adf_ctl_ioctl,
71 };
72
73 struct adf_ctl_drv_info {
74 unsigned int major;
75 struct cdev drv_cdev;
76 struct class *drv_class;
77 };
78
79 static struct adf_ctl_drv_info adt_ctl_drv;
80
81 static void adf_chr_drv_destroy(void)
82 {
83 device_destroy(adt_ctl_drv.drv_class, MKDEV(adt_ctl_drv.major, 0));
84 cdev_del(&adt_ctl_drv.drv_cdev);
85 class_destroy(adt_ctl_drv.drv_class);
86 unregister_chrdev_region(MKDEV(adt_ctl_drv.major, 0), 1);
87 }
88
89 static int adf_chr_drv_create(void)
90 {
91 dev_t dev_id;
92 struct device *drv_device;
93
94 if (alloc_chrdev_region(&dev_id, 0, 1, DEVICE_NAME)) {
95 pr_err("QAT: unable to allocate chrdev region\n");
96 return -EFAULT;
97 }
98
99 adt_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
100 if (IS_ERR(adt_ctl_drv.drv_class)) {
101 pr_err("QAT: class_create failed for adf_ctl\n");
102 goto err_chrdev_unreg;
103 }
104 adt_ctl_drv.major = MAJOR(dev_id);
105 cdev_init(&adt_ctl_drv.drv_cdev, &adf_ctl_ops);
106 if (cdev_add(&adt_ctl_drv.drv_cdev, dev_id, 1)) {
107 pr_err("QAT: cdev add failed\n");
108 goto err_class_destr;
109 }
110
111 drv_device = device_create(adt_ctl_drv.drv_class, NULL,
112 MKDEV(adt_ctl_drv.major, 0),
113 NULL, DEVICE_NAME);
114 if (IS_ERR(drv_device)) {
115 pr_err("QAT: failed to create device\n");
116 goto err_cdev_del;
117 }
118 return 0;
119 err_cdev_del:
120 cdev_del(&adt_ctl_drv.drv_cdev);
121 err_class_destr:
122 class_destroy(adt_ctl_drv.drv_class);
123 err_chrdev_unreg:
124 unregister_chrdev_region(dev_id, 1);
125 return -EFAULT;
126 }
127
128 static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
129 unsigned long arg)
130 {
131 struct adf_user_cfg_ctl_data *cfg_data;
132
133 cfg_data = kzalloc(sizeof(*cfg_data), GFP_KERNEL);
134 if (!cfg_data)
135 return -ENOMEM;
136
137 /* Initialize device id to NO DEVICE as 0 is a valid device id */
138 cfg_data->device_id = ADF_CFG_NO_DEVICE;
139
140 if (copy_from_user(cfg_data, (void __user *)arg, sizeof(*cfg_data))) {
141 pr_err("QAT: failed to copy from user cfg_data.\n");
142 kfree(cfg_data);
143 return -EIO;
144 }
145
146 *ctl_data = cfg_data;
147 return 0;
148 }
149
150 static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
151 const char *section,
152 const struct adf_user_cfg_key_val *key_val)
153 {
154 if (key_val->type == ADF_HEX) {
155 long *ptr = (long *)key_val->val;
156 long val = *ptr;
157
158 if (adf_cfg_add_key_value_param(accel_dev, section,
159 key_val->key, (void *)val,
160 key_val->type)) {
161 pr_err("QAT: failed to add keyvalue.\n");
162 return -EFAULT;
163 }
164 } else {
165 if (adf_cfg_add_key_value_param(accel_dev, section,
166 key_val->key, key_val->val,
167 key_val->type)) {
168 pr_err("QAT: failed to add keyvalue.\n");
169 return -EFAULT;
170 }
171 }
172 return 0;
173 }
174
175 static int adf_copy_key_value_data(struct adf_accel_dev *accel_dev,
176 struct adf_user_cfg_ctl_data *ctl_data)
177 {
178 struct adf_user_cfg_key_val key_val;
179 struct adf_user_cfg_key_val *params_head;
180 struct adf_user_cfg_section section, *section_head;
181
182 section_head = ctl_data->config_section;
183
184 while (section_head) {
185 if (copy_from_user(&section, (void __user *)section_head,
186 sizeof(*section_head))) {
187 pr_err("QAT: failed to copy section info\n");
188 goto out_err;
189 }
190
191 if (adf_cfg_section_add(accel_dev, section.name)) {
192 pr_err("QAT: failed to add section.\n");
193 goto out_err;
194 }
195
196 params_head = section_head->params;
197
198 while (params_head) {
199 if (copy_from_user(&key_val, (void __user *)params_head,
200 sizeof(key_val))) {
201 pr_err("QAT: Failed to copy keyvalue.\n");
202 goto out_err;
203 }
204 if (adf_add_key_value_data(accel_dev, section.name,
205 &key_val)) {
206 goto out_err;
207 }
208 params_head = key_val.next;
209 }
210 section_head = section.next;
211 }
212 return 0;
213 out_err:
214 adf_cfg_del_all(accel_dev);
215 return -EFAULT;
216 }
217
218 static int adf_ctl_ioctl_dev_config(struct file *fp, unsigned int cmd,
219 unsigned long arg)
220 {
221 int ret;
222 struct adf_user_cfg_ctl_data *ctl_data;
223 struct adf_accel_dev *accel_dev;
224
225 ret = adf_ctl_alloc_resources(&ctl_data, arg);
226 if (ret)
227 return ret;
228
229 accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
230 if (!accel_dev) {
231 ret = -EFAULT;
232 goto out;
233 }
234
235 if (adf_dev_started(accel_dev)) {
236 ret = -EFAULT;
237 goto out;
238 }
239
240 if (adf_copy_key_value_data(accel_dev, ctl_data)) {
241 ret = -EFAULT;
242 goto out;
243 }
244 set_bit(ADF_STATUS_CONFIGURED, &accel_dev->status);
245 out:
246 kfree(ctl_data);
247 return ret;
248 }
249
250 static int adf_ctl_is_device_in_use(int id)
251 {
252 struct list_head *itr, *head = adf_devmgr_get_head();
253
254 list_for_each(itr, head) {
255 struct adf_accel_dev *dev =
256 list_entry(itr, struct adf_accel_dev, list);
257
258 if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
259 if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
260 pr_info("QAT: device qat_dev%d is busy\n",
261 dev->accel_id);
262 return -EBUSY;
263 }
264 }
265 }
266 return 0;
267 }
268
269 static int adf_ctl_stop_devices(uint32_t id)
270 {
271 struct list_head *itr, *head = adf_devmgr_get_head();
272 int ret = 0;
273
274 list_for_each(itr, head) {
275 struct adf_accel_dev *accel_dev =
276 list_entry(itr, struct adf_accel_dev, list);
277 if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
278 if (!adf_dev_started(accel_dev))
279 continue;
280
281 if (adf_dev_stop(accel_dev)) {
282 pr_err("QAT: Failed to stop qat_dev%d\n", id);
283 ret = -EFAULT;
284 }
285 }
286 }
287 return ret;
288 }
289
290 static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
291 unsigned long arg)
292 {
293 int ret;
294 struct adf_user_cfg_ctl_data *ctl_data;
295
296 ret = adf_ctl_alloc_resources(&ctl_data, arg);
297 if (ret)
298 return ret;
299
300 if (adf_devmgr_verify_id(ctl_data->device_id)) {
301 pr_err("QAT: Device %d not found\n", ctl_data->device_id);
302 ret = -ENODEV;
303 goto out;
304 }
305
306 ret = adf_ctl_is_device_in_use(ctl_data->device_id);
307 if (ret)
308 goto out;
309
310 if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
311 pr_info("QAT: Stopping all acceleration devices.\n");
312 else
313 pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
314 ctl_data->device_id);
315
316 ret = adf_ctl_stop_devices(ctl_data->device_id);
317 if (ret)
318 pr_err("QAT: failed to stop device.\n");
319 out:
320 kfree(ctl_data);
321 return ret;
322 }
323
324 static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
325 unsigned long arg)
326 {
327 int ret;
328 struct adf_user_cfg_ctl_data *ctl_data;
329 struct adf_accel_dev *accel_dev;
330
331 ret = adf_ctl_alloc_resources(&ctl_data, arg);
332 if (ret)
333 return ret;
334
335 accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
336 if (!accel_dev) {
337 pr_err("QAT: Device %d not found\n", ctl_data->device_id);
338 ret = -ENODEV;
339 goto out;
340 }
341
342 if (!adf_dev_started(accel_dev)) {
343 pr_info("QAT: Starting acceleration device qat_dev%d.\n",
344 ctl_data->device_id);
345 ret = adf_dev_start(accel_dev);
346 } else {
347 pr_info("QAT: Acceleration device qat_dev%d already started.\n",
348 ctl_data->device_id);
349 }
350 if (ret) {
351 pr_err("QAT: Failed to start qat_dev%d\n", ctl_data->device_id);
352 adf_dev_stop(accel_dev);
353 }
354 out:
355 kfree(ctl_data);
356 return ret;
357 }
358
359 static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
360 unsigned long arg)
361 {
362 uint32_t num_devices = 0;
363
364 adf_devmgr_get_num_dev(&num_devices);
365 if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
366 return -EFAULT;
367
368 return 0;
369 }
370
371 static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
372 unsigned long arg)
373 {
374 struct adf_hw_device_data *hw_data;
375 struct adf_dev_status_info dev_info;
376 struct adf_accel_dev *accel_dev;
377
378 if (copy_from_user(&dev_info, (void __user *)arg,
379 sizeof(struct adf_dev_status_info))) {
380 pr_err("QAT: failed to copy from user.\n");
381 return -EFAULT;
382 }
383
384 accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
385 if (!accel_dev) {
386 pr_err("QAT: Device %d not found\n", dev_info.accel_id);
387 return -ENODEV;
388 }
389 hw_data = accel_dev->hw_device;
390 dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
391 dev_info.num_ae = hw_data->get_num_aes(hw_data);
392 dev_info.num_accel = hw_data->get_num_accels(hw_data);
393 dev_info.num_logical_accel = hw_data->num_logical_accel;
394 dev_info.banks_per_accel = hw_data->num_banks
395 / hw_data->num_logical_accel;
396 strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
397 dev_info.instance_id = hw_data->instance_id;
398 dev_info.type = hw_data->dev_class->type;
399 dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
400 dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
401 dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
402
403 if (copy_to_user((void __user *)arg, &dev_info,
404 sizeof(struct adf_dev_status_info))) {
405 pr_err("QAT: failed to copy status.\n");
406 return -EFAULT;
407 }
408 return 0;
409 }
410
411 static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
412 {
413 int ret;
414
415 if (mutex_lock_interruptible(&adf_ctl_lock))
416 return -EFAULT;
417
418 switch (cmd) {
419 case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
420 ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
421 break;
422
423 case IOCTL_STOP_ACCEL_DEV:
424 ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
425 break;
426
427 case IOCTL_START_ACCEL_DEV:
428 ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
429 break;
430
431 case IOCTL_GET_NUM_DEVICES:
432 ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
433 break;
434
435 case IOCTL_STATUS_ACCEL_DEV:
436 ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
437 break;
438 default:
439 pr_err("QAT: Invalid ioctl\n");
440 ret = -EFAULT;
441 break;
442 }
443 mutex_unlock(&adf_ctl_lock);
444 return ret;
445 }
446
447 static int __init adf_register_ctl_device_driver(void)
448 {
449 mutex_init(&adf_ctl_lock);
450
451 if (qat_algs_init())
452 goto err_algs_init;
453
454 if (adf_chr_drv_create())
455 goto err_chr_dev;
456
457 if (adf_init_aer())
458 goto err_aer;
459
460 if (qat_crypto_register())
461 goto err_crypto_register;
462
463 return 0;
464
465 err_crypto_register:
466 adf_exit_aer();
467 err_aer:
468 adf_chr_drv_destroy();
469 err_chr_dev:
470 qat_algs_exit();
471 err_algs_init:
472 mutex_destroy(&adf_ctl_lock);
473 return -EFAULT;
474 }
475
476 static void __exit adf_unregister_ctl_device_driver(void)
477 {
478 adf_chr_drv_destroy();
479 adf_exit_aer();
480 qat_crypto_unregister();
481 qat_algs_exit();
482 mutex_destroy(&adf_ctl_lock);
483 }
484
485 module_init(adf_register_ctl_device_driver);
486 module_exit(adf_unregister_ctl_device_driver);
487 MODULE_LICENSE("Dual BSD/GPL");
488 MODULE_AUTHOR("Intel");
489 MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
490 MODULE_ALIAS("intel_qat");