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