1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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#include <linux/crypto.h>
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
80static struct adf_ctl_drv_info adf_ctl_drv;
81
82static void adf_chr_drv_destroy(void)
83{
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);
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
100 adf_ctl_drv.drv_class = class_create(THIS_MODULE, DEVICE_NAME);
101 if (IS_ERR(adf_ctl_drv.drv_class)) {
102 pr_err("QAT: class_create failed for adf_ctl\n");
103 goto err_chrdev_unreg;
104 }
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)) {
108 pr_err("QAT: cdev add failed\n");
109 goto err_class_destr;
110 }
111
112 drv_device = device_create(adf_ctl_drv.drv_class, NULL,
113 MKDEV(adf_ctl_drv.major, 0),
114 NULL, DEVICE_NAME);
115 if (IS_ERR(drv_device)) {
116 pr_err("QAT: failed to create device\n");
117 goto err_cdev_del;
118 }
119 return 0;
120err_cdev_del:
121 cdev_del(&adf_ctl_drv.drv_cdev);
122err_class_destr:
123 class_destroy(adf_ctl_drv.drv_class);
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
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)) {
162 dev_err(&GET_DEV(accel_dev),
163 "failed to add hex keyvalue.\n");
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)) {
170 dev_err(&GET_DEV(accel_dev),
171 "failed to add keyvalue.\n");
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(§ion, (void __user *)section_head,
189 sizeof(*section_head))) {
190 dev_err(&GET_DEV(accel_dev),
191 "failed to copy section info\n");
192 goto out_err;
193 }
194
195 if (adf_cfg_section_add(accel_dev, section.name)) {
196 dev_err(&GET_DEV(accel_dev),
197 "failed to add section.\n");
198 goto out_err;
199 }
200
201 params_head = section.params;
202
203 while (params_head) {
204 if (copy_from_user(&key_val, (void __user *)params_head,
205 sizeof(key_val))) {
206 dev_err(&GET_DEV(accel_dev),
207 "Failed to copy keyvalue.\n");
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{
258 struct adf_accel_dev *dev;
259
260 list_for_each_entry(dev, adf_devmgr_get_head(), list) {
261 if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
262 if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
263 dev_info(&GET_DEV(dev),
264 "device qat_dev%d is busy\n",
265 dev->accel_id);
266 return -EBUSY;
267 }
268 }
269 }
270 return 0;
271}
272
273static void adf_ctl_stop_devices(uint32_t id)
274{
275 struct adf_accel_dev *accel_dev;
276
277 list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
278 if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
279 if (!adf_dev_started(accel_dev))
280 continue;
281
282
283 if (!accel_dev->is_vf)
284 continue;
285
286 adf_dev_stop(accel_dev);
287 adf_dev_shutdown(accel_dev);
288 }
289 }
290
291 list_for_each_entry(accel_dev, adf_devmgr_get_head(), list) {
292 if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
293 if (!adf_dev_started(accel_dev))
294 continue;
295
296 adf_dev_stop(accel_dev);
297 adf_dev_shutdown(accel_dev);
298 }
299 }
300}
301
302static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
303 unsigned long arg)
304{
305 int ret;
306 struct adf_user_cfg_ctl_data *ctl_data;
307
308 ret = adf_ctl_alloc_resources(&ctl_data, arg);
309 if (ret)
310 return ret;
311
312 if (adf_devmgr_verify_id(ctl_data->device_id)) {
313 pr_err("QAT: Device %d not found\n", ctl_data->device_id);
314 ret = -ENODEV;
315 goto out;
316 }
317
318 ret = adf_ctl_is_device_in_use(ctl_data->device_id);
319 if (ret)
320 goto out;
321
322 if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
323 pr_info("QAT: Stopping all acceleration devices.\n");
324 else
325 pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
326 ctl_data->device_id);
327
328 adf_ctl_stop_devices(ctl_data->device_id);
329
330out:
331 kfree(ctl_data);
332 return ret;
333}
334
335static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
336 unsigned long arg)
337{
338 int ret;
339 struct adf_user_cfg_ctl_data *ctl_data;
340 struct adf_accel_dev *accel_dev;
341
342 ret = adf_ctl_alloc_resources(&ctl_data, arg);
343 if (ret)
344 return ret;
345
346 ret = -ENODEV;
347 accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
348 if (!accel_dev)
349 goto out;
350
351 if (!adf_dev_started(accel_dev)) {
352 dev_info(&GET_DEV(accel_dev),
353 "Starting acceleration device qat_dev%d.\n",
354 ctl_data->device_id);
355 ret = adf_dev_init(accel_dev);
356 if (!ret)
357 ret = adf_dev_start(accel_dev);
358 } else {
359 dev_info(&GET_DEV(accel_dev),
360 "Acceleration device qat_dev%d already started.\n",
361 ctl_data->device_id);
362 }
363 if (ret) {
364 dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
365 ctl_data->device_id);
366 adf_dev_stop(accel_dev);
367 adf_dev_shutdown(accel_dev);
368 }
369out:
370 kfree(ctl_data);
371 return ret;
372}
373
374static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
375 unsigned long arg)
376{
377 uint32_t num_devices = 0;
378
379 adf_devmgr_get_num_dev(&num_devices);
380 if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
381 return -EFAULT;
382
383 return 0;
384}
385
386static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
387 unsigned long arg)
388{
389 struct adf_hw_device_data *hw_data;
390 struct adf_dev_status_info dev_info;
391 struct adf_accel_dev *accel_dev;
392
393 if (copy_from_user(&dev_info, (void __user *)arg,
394 sizeof(struct adf_dev_status_info))) {
395 pr_err("QAT: failed to copy from user.\n");
396 return -EFAULT;
397 }
398
399 accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
400 if (!accel_dev)
401 return -ENODEV;
402
403 hw_data = accel_dev->hw_device;
404 dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
405 dev_info.num_ae = hw_data->get_num_aes(hw_data);
406 dev_info.num_accel = hw_data->get_num_accels(hw_data);
407 dev_info.num_logical_accel = hw_data->num_logical_accel;
408 dev_info.banks_per_accel = hw_data->num_banks
409 / hw_data->num_logical_accel;
410 strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
411 dev_info.instance_id = hw_data->instance_id;
412 dev_info.type = hw_data->dev_class->type;
413 dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
414 dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
415 dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
416
417 if (copy_to_user((void __user *)arg, &dev_info,
418 sizeof(struct adf_dev_status_info))) {
419 dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
420 return -EFAULT;
421 }
422 return 0;
423}
424
425static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
426{
427 int ret;
428
429 if (mutex_lock_interruptible(&adf_ctl_lock))
430 return -EFAULT;
431
432 switch (cmd) {
433 case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
434 ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
435 break;
436
437 case IOCTL_STOP_ACCEL_DEV:
438 ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
439 break;
440
441 case IOCTL_START_ACCEL_DEV:
442 ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
443 break;
444
445 case IOCTL_GET_NUM_DEVICES:
446 ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
447 break;
448
449 case IOCTL_STATUS_ACCEL_DEV:
450 ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
451 break;
452 default:
453 pr_err("QAT: Invalid ioctl\n");
454 ret = -EFAULT;
455 break;
456 }
457 mutex_unlock(&adf_ctl_lock);
458 return ret;
459}
460
461static int __init adf_register_ctl_device_driver(void)
462{
463 mutex_init(&adf_ctl_lock);
464
465 if (adf_chr_drv_create())
466 goto err_chr_dev;
467
468 if (adf_init_aer())
469 goto err_aer;
470
471 if (adf_init_pf_wq())
472 goto err_pf_wq;
473
474 if (adf_init_vf_wq())
475 goto err_vf_wq;
476
477 if (qat_crypto_register())
478 goto err_crypto_register;
479
480 return 0;
481
482err_crypto_register:
483 adf_exit_vf_wq();
484err_vf_wq:
485 adf_exit_pf_wq();
486err_pf_wq:
487 adf_exit_aer();
488err_aer:
489 adf_chr_drv_destroy();
490err_chr_dev:
491 mutex_destroy(&adf_ctl_lock);
492 return -EFAULT;
493}
494
495static void __exit adf_unregister_ctl_device_driver(void)
496{
497 adf_chr_drv_destroy();
498 adf_exit_aer();
499 adf_exit_vf_wq();
500 adf_exit_pf_wq();
501 qat_crypto_unregister();
502 adf_clean_vf_map(false);
503 mutex_destroy(&adf_ctl_lock);
504}
505
506module_init(adf_register_ctl_device_driver);
507module_exit(adf_unregister_ctl_device_driver);
508MODULE_LICENSE("Dual BSD/GPL");
509MODULE_AUTHOR("Intel");
510MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
511MODULE_ALIAS_CRYPTO("intel_qat");
512MODULE_VERSION(ADF_DRV_VERSION);
513