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#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	/* 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)) {
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(&section, (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_head->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 list_head *itr, *head = adf_devmgr_get_head();
259
260	list_for_each(itr, head) {
261		struct adf_accel_dev *dev =
262				list_entry(itr, struct adf_accel_dev, list);
263
264		if (id == dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
265			if (adf_devmgr_in_reset(dev) || adf_dev_in_use(dev)) {
266				dev_info(&GET_DEV(dev),
267					 "device qat_dev%d is busy\n",
268					 dev->accel_id);
269				return -EBUSY;
270			}
271		}
272	}
273	return 0;
274}
275
276static int adf_ctl_stop_devices(uint32_t id)
277{
278	struct list_head *itr, *head = adf_devmgr_get_head();
279	int ret = 0;
280
281	list_for_each(itr, head) {
282		struct adf_accel_dev *accel_dev =
283				list_entry(itr, struct adf_accel_dev, list);
284		if (id == accel_dev->accel_id || id == ADF_CFG_ALL_DEVICES) {
285			if (!adf_dev_started(accel_dev))
286				continue;
287
288			if (adf_dev_stop(accel_dev)) {
289				dev_err(&GET_DEV(accel_dev),
290					"Failed to stop qat_dev%d\n", id);
291				ret = -EFAULT;
292			} else {
293				adf_dev_shutdown(accel_dev);
294			}
295		}
296	}
297	return ret;
298}
299
300static int adf_ctl_ioctl_dev_stop(struct file *fp, unsigned int cmd,
301				  unsigned long arg)
302{
303	int ret;
304	struct adf_user_cfg_ctl_data *ctl_data;
305
306	ret = adf_ctl_alloc_resources(&ctl_data, arg);
307	if (ret)
308		return ret;
309
310	if (adf_devmgr_verify_id(ctl_data->device_id)) {
311		pr_err("QAT: Device %d not found\n", ctl_data->device_id);
312		ret = -ENODEV;
313		goto out;
314	}
315
316	ret = adf_ctl_is_device_in_use(ctl_data->device_id);
317	if (ret)
318		goto out;
319
320	if (ctl_data->device_id == ADF_CFG_ALL_DEVICES)
321		pr_info("QAT: Stopping all acceleration devices.\n");
322	else
323		pr_info("QAT: Stopping acceleration device qat_dev%d.\n",
324			ctl_data->device_id);
325
326	ret = adf_ctl_stop_devices(ctl_data->device_id);
327	if (ret)
328		pr_err("QAT: failed to stop device.\n");
329out:
330	kfree(ctl_data);
331	return ret;
332}
333
334static int adf_ctl_ioctl_dev_start(struct file *fp, unsigned int cmd,
335				   unsigned long arg)
336{
337	int ret;
338	struct adf_user_cfg_ctl_data *ctl_data;
339	struct adf_accel_dev *accel_dev;
340
341	ret = adf_ctl_alloc_resources(&ctl_data, arg);
342	if (ret)
343		return ret;
344
345	accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
346	if (!accel_dev) {
347		pr_err("QAT: Device %d not found\n", ctl_data->device_id);
348		ret = -ENODEV;
349		goto out;
350	}
351
352	if (!adf_dev_started(accel_dev)) {
353		dev_info(&GET_DEV(accel_dev),
354			 "Starting acceleration device qat_dev%d.\n",
355			 ctl_data->device_id);
356		ret = adf_dev_init(accel_dev);
357		if (!ret)
358			ret = adf_dev_start(accel_dev);
359	} else {
360		dev_info(&GET_DEV(accel_dev),
361			 "Acceleration device qat_dev%d already started.\n",
362			 ctl_data->device_id);
363	}
364	if (ret) {
365		dev_err(&GET_DEV(accel_dev), "Failed to start qat_dev%d\n",
366			ctl_data->device_id);
367		adf_dev_stop(accel_dev);
368		adf_dev_shutdown(accel_dev);
369	}
370out:
371	kfree(ctl_data);
372	return ret;
373}
374
375static int adf_ctl_ioctl_get_num_devices(struct file *fp, unsigned int cmd,
376					 unsigned long arg)
377{
378	uint32_t num_devices = 0;
379
380	adf_devmgr_get_num_dev(&num_devices);
381	if (copy_to_user((void __user *)arg, &num_devices, sizeof(num_devices)))
382		return -EFAULT;
383
384	return 0;
385}
386
387static int adf_ctl_ioctl_get_status(struct file *fp, unsigned int cmd,
388				    unsigned long arg)
389{
390	struct adf_hw_device_data *hw_data;
391	struct adf_dev_status_info dev_info;
392	struct adf_accel_dev *accel_dev;
393
394	if (copy_from_user(&dev_info, (void __user *)arg,
395			   sizeof(struct adf_dev_status_info))) {
396		pr_err("QAT: failed to copy from user.\n");
397		return -EFAULT;
398	}
399
400	accel_dev = adf_devmgr_get_dev_by_id(dev_info.accel_id);
401	if (!accel_dev) {
402		pr_err("QAT: Device %d not found\n", dev_info.accel_id);
403		return -ENODEV;
404	}
405	hw_data = accel_dev->hw_device;
406	dev_info.state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
407	dev_info.num_ae = hw_data->get_num_aes(hw_data);
408	dev_info.num_accel = hw_data->get_num_accels(hw_data);
409	dev_info.num_logical_accel = hw_data->num_logical_accel;
410	dev_info.banks_per_accel = hw_data->num_banks
411					/ hw_data->num_logical_accel;
412	strlcpy(dev_info.name, hw_data->dev_class->name, sizeof(dev_info.name));
413	dev_info.instance_id = hw_data->instance_id;
414	dev_info.type = hw_data->dev_class->type;
415	dev_info.bus = accel_to_pci_dev(accel_dev)->bus->number;
416	dev_info.dev = PCI_SLOT(accel_to_pci_dev(accel_dev)->devfn);
417	dev_info.fun = PCI_FUNC(accel_to_pci_dev(accel_dev)->devfn);
418
419	if (copy_to_user((void __user *)arg, &dev_info,
420			 sizeof(struct adf_dev_status_info))) {
421		dev_err(&GET_DEV(accel_dev), "failed to copy status.\n");
422		return -EFAULT;
423	}
424	return 0;
425}
426
427static long adf_ctl_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
428{
429	int ret;
430
431	if (mutex_lock_interruptible(&adf_ctl_lock))
432		return -EFAULT;
433
434	switch (cmd) {
435	case IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS:
436		ret = adf_ctl_ioctl_dev_config(fp, cmd, arg);
437		break;
438
439	case IOCTL_STOP_ACCEL_DEV:
440		ret = adf_ctl_ioctl_dev_stop(fp, cmd, arg);
441		break;
442
443	case IOCTL_START_ACCEL_DEV:
444		ret = adf_ctl_ioctl_dev_start(fp, cmd, arg);
445		break;
446
447	case IOCTL_GET_NUM_DEVICES:
448		ret = adf_ctl_ioctl_get_num_devices(fp, cmd, arg);
449		break;
450
451	case IOCTL_STATUS_ACCEL_DEV:
452		ret = adf_ctl_ioctl_get_status(fp, cmd, arg);
453		break;
454	default:
455		pr_err("QAT: Invalid ioctl\n");
456		ret = -EFAULT;
457		break;
458	}
459	mutex_unlock(&adf_ctl_lock);
460	return ret;
461}
462
463static int __init adf_register_ctl_device_driver(void)
464{
465	mutex_init(&adf_ctl_lock);
466
467	if (qat_algs_init())
468		goto err_algs_init;
469
470	if (adf_chr_drv_create())
471		goto err_chr_dev;
472
473	if (adf_init_aer())
474		goto err_aer;
475
476	if (qat_crypto_register())
477		goto err_crypto_register;
478
479	return 0;
480
481err_crypto_register:
482	adf_exit_aer();
483err_aer:
484	adf_chr_drv_destroy();
485err_chr_dev:
486	qat_algs_exit();
487err_algs_init:
488	mutex_destroy(&adf_ctl_lock);
489	return -EFAULT;
490}
491
492static void __exit adf_unregister_ctl_device_driver(void)
493{
494	adf_chr_drv_destroy();
495	adf_exit_aer();
496	qat_crypto_unregister();
497	qat_algs_exit();
498	mutex_destroy(&adf_ctl_lock);
499}
500
501module_init(adf_register_ctl_device_driver);
502module_exit(adf_unregister_ctl_device_driver);
503MODULE_LICENSE("Dual BSD/GPL");
504MODULE_AUTHOR("Intel");
505MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
506MODULE_ALIAS_CRYPTO("intel_qat");
507