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 int adf_ctl_stop_devices(uint32_t id)
274{
275 struct adf_accel_dev *accel_dev;
276 int ret = 0;
277
278 list_for_each_entry_reverse(accel_dev, adf_devmgr_get_head(), list) {
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)) {
284 dev_err(&GET_DEV(accel_dev),
285 "Failed to stop qat_dev%d\n", id);
286 ret = -EFAULT;
287 } else {
288 adf_dev_shutdown(accel_dev);
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
340 ret = -ENODEV;
341 accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
342 if (!accel_dev)
343 goto out;
344
345 if (!adf_dev_started(accel_dev)) {
346 dev_info(&GET_DEV(accel_dev),
347 "Starting acceleration device qat_dev%d.\n",
348 ctl_data->device_id);
349 ret = adf_dev_init(accel_dev);
350 if (!ret)
351 ret = adf_dev_start(accel_dev);
352 } else {
353 dev_info(&GET_DEV(accel_dev),
354 "Acceleration device qat_dev%d already started.\n",
355 ctl_data->device_id);
356 }
357 if (ret) {
358 dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
359 ctl_data->device_id);
360 adf_dev_stop(accel_dev);
361 adf_dev_shutdown(accel_dev);
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);
394 if (!accel_dev)
395 return -ENODEV;
396
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))) {
413 dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
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:
447 pr_err("QAT: Invalid ioctl\n");
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
459 if (adf_chr_drv_create())
460 goto err_chr_dev;
461
462 if (adf_init_aer())
463 goto err_aer;
464
465 if (adf_init_pf_wq())
466 goto err_pf_wq;
467
468 if (qat_crypto_register())
469 goto err_crypto_register;
470
471 return 0;
472
473err_crypto_register:
474 adf_exit_pf_wq();
475err_pf_wq:
476 adf_exit_aer();
477err_aer:
478 adf_chr_drv_destroy();
479err_chr_dev:
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();
488 adf_exit_pf_wq();
489 qat_crypto_unregister();
490 adf_clean_vf_map(false);
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");
499MODULE_ALIAS_CRYPTO("intel_qat");
500MODULE_VERSION(ADF_DRV_VERSION);
501