1266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */
2266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */
3266b0663SKrzysztof Zdziarski #include "qat_freebsd.h"
4266b0663SKrzysztof Zdziarski #include "adf_cfg.h"
5266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
6266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
7266b0663SKrzysztof Zdziarski #include "icp_qat_uclo.h"
8266b0663SKrzysztof Zdziarski #include "icp_qat_fw.h"
9266b0663SKrzysztof Zdziarski #include "icp_qat_fw_init_admin.h"
10266b0663SKrzysztof Zdziarski #include "adf_cfg_strings.h"
11266b0663SKrzysztof Zdziarski #include "adf_uio_control.h"
12266b0663SKrzysztof Zdziarski #include "adf_uio_cleanup.h"
13266b0663SKrzysztof Zdziarski #include "adf_uio.h"
14266b0663SKrzysztof Zdziarski #include "adf_transport_access_macros.h"
15266b0663SKrzysztof Zdziarski #include "adf_transport_internal.h"
16266b0663SKrzysztof Zdziarski #include <sys/bus.h>
17266b0663SKrzysztof Zdziarski #include <sys/lock.h>
18266b0663SKrzysztof Zdziarski #include <sys/kernel.h>
19266b0663SKrzysztof Zdziarski #include <sys/module.h>
20266b0663SKrzysztof Zdziarski #include <sys/sx.h>
21266b0663SKrzysztof Zdziarski #include <sys/malloc.h>
22266b0663SKrzysztof Zdziarski #include <machine/atomic.h>
23266b0663SKrzysztof Zdziarski #include <dev/pci/pcivar.h>
24266b0663SKrzysztof Zdziarski #include <sys/conf.h>
25266b0663SKrzysztof Zdziarski #include <sys/systm.h>
26266b0663SKrzysztof Zdziarski #include <sys/queue.h>
27266b0663SKrzysztof Zdziarski #include <sys/proc.h>
28266b0663SKrzysztof Zdziarski #include <sys/types.h>
29266b0663SKrzysztof Zdziarski #include <sys/priv.h>
30266b0663SKrzysztof Zdziarski #include <linux/list.h>
31266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
32266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
33266b0663SKrzysztof Zdziarski #include "adf_cfg.h"
34266b0663SKrzysztof Zdziarski #include "adf_cfg_common.h"
35266b0663SKrzysztof Zdziarski #include "adf_cfg_user.h"
36266b0663SKrzysztof Zdziarski #include "adf_heartbeat.h"
37266b0663SKrzysztof Zdziarski #include "adf_cfg_device.h"
38266b0663SKrzysztof Zdziarski
39266b0663SKrzysztof Zdziarski #define DEVICE_NAME "qat_adf_ctl"
40266b0663SKrzysztof Zdziarski
41266b0663SKrzysztof Zdziarski static struct sx adf_ctl_lock;
42266b0663SKrzysztof Zdziarski
43266b0663SKrzysztof Zdziarski static d_ioctl_t adf_ctl_ioctl;
44266b0663SKrzysztof Zdziarski
45266b0663SKrzysztof Zdziarski void *misc_counter;
46266b0663SKrzysztof Zdziarski
47266b0663SKrzysztof Zdziarski static struct cdevsw adf_ctl_cdevsw = {
48266b0663SKrzysztof Zdziarski .d_version = D_VERSION,
49266b0663SKrzysztof Zdziarski .d_ioctl = adf_ctl_ioctl,
50266b0663SKrzysztof Zdziarski .d_name = DEVICE_NAME,
51266b0663SKrzysztof Zdziarski };
52266b0663SKrzysztof Zdziarski
53266b0663SKrzysztof Zdziarski static struct cdev *adf_ctl_dev;
54266b0663SKrzysztof Zdziarski
adf_chr_drv_destroy(void)55266b0663SKrzysztof Zdziarski static void adf_chr_drv_destroy(void)
56266b0663SKrzysztof Zdziarski {
57266b0663SKrzysztof Zdziarski destroy_dev(adf_ctl_dev);
58266b0663SKrzysztof Zdziarski }
59266b0663SKrzysztof Zdziarski
60266b0663SKrzysztof Zdziarski struct adf_user_addr_info {
61266b0663SKrzysztof Zdziarski struct list_head list;
62266b0663SKrzysztof Zdziarski void *user_addr;
63266b0663SKrzysztof Zdziarski };
64266b0663SKrzysztof Zdziarski
adf_chr_drv_create(void)65266b0663SKrzysztof Zdziarski static int adf_chr_drv_create(void)
66266b0663SKrzysztof Zdziarski {
67266b0663SKrzysztof Zdziarski adf_ctl_dev = make_dev(&adf_ctl_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
68266b0663SKrzysztof Zdziarski DEVICE_NAME);
69266b0663SKrzysztof Zdziarski
70266b0663SKrzysztof Zdziarski if (!adf_ctl_dev) {
71266b0663SKrzysztof Zdziarski printf("QAT: failed to create device\n");
72266b0663SKrzysztof Zdziarski goto err_cdev_del;
73266b0663SKrzysztof Zdziarski }
74266b0663SKrzysztof Zdziarski return 0;
75266b0663SKrzysztof Zdziarski err_cdev_del:
76266b0663SKrzysztof Zdziarski return EFAULT;
77266b0663SKrzysztof Zdziarski }
78266b0663SKrzysztof Zdziarski
adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data ** ctl_data,caddr_t arg)79266b0663SKrzysztof Zdziarski static int adf_ctl_alloc_resources(struct adf_user_cfg_ctl_data **ctl_data,
80266b0663SKrzysztof Zdziarski caddr_t arg)
81266b0663SKrzysztof Zdziarski {
82266b0663SKrzysztof Zdziarski *ctl_data = (struct adf_user_cfg_ctl_data *)arg;
83266b0663SKrzysztof Zdziarski return 0;
84266b0663SKrzysztof Zdziarski }
85266b0663SKrzysztof Zdziarski
adf_copy_keyval_to_user(struct adf_accel_dev * accel_dev,struct adf_user_cfg_ctl_data * ctl_data)86266b0663SKrzysztof Zdziarski static int adf_copy_keyval_to_user(struct adf_accel_dev *accel_dev,
87266b0663SKrzysztof Zdziarski struct adf_user_cfg_ctl_data *ctl_data)
88266b0663SKrzysztof Zdziarski {
89266b0663SKrzysztof Zdziarski struct adf_user_cfg_key_val key_val;
90266b0663SKrzysztof Zdziarski struct adf_user_cfg_section section;
91266b0663SKrzysztof Zdziarski char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
92266b0663SKrzysztof Zdziarski char *user_ptr;
93266b0663SKrzysztof Zdziarski
94266b0663SKrzysztof Zdziarski if (copyin(ctl_data->config_section, §ion,
95266b0663SKrzysztof Zdziarski sizeof(struct adf_user_cfg_section))) {
96266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
97266b0663SKrzysztof Zdziarski "failed to copy section info\n");
98266b0663SKrzysztof Zdziarski return EFAULT;
99266b0663SKrzysztof Zdziarski }
100266b0663SKrzysztof Zdziarski
101266b0663SKrzysztof Zdziarski if (copyin(section.params, &key_val,
102266b0663SKrzysztof Zdziarski sizeof(struct adf_user_cfg_key_val))) {
103266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev), "failed to copy key val\n");
104266b0663SKrzysztof Zdziarski return EFAULT;
105266b0663SKrzysztof Zdziarski }
106266b0663SKrzysztof Zdziarski
107266b0663SKrzysztof Zdziarski user_ptr = ((char *)section.params) + ADF_CFG_MAX_KEY_LEN_IN_BYTES;
108266b0663SKrzysztof Zdziarski
109266b0663SKrzysztof Zdziarski if (adf_cfg_get_param_value(
110266b0663SKrzysztof Zdziarski accel_dev, section.name, key_val.key, val)) {
111266b0663SKrzysztof Zdziarski return EFAULT;
112266b0663SKrzysztof Zdziarski }
113266b0663SKrzysztof Zdziarski
114266b0663SKrzysztof Zdziarski if (copyout(val, user_ptr,
115266b0663SKrzysztof Zdziarski ADF_CFG_MAX_VAL_LEN_IN_BYTES)) {
116266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
117266b0663SKrzysztof Zdziarski "failed to copy keyvalue to user!\n");
118266b0663SKrzysztof Zdziarski return EFAULT;
119266b0663SKrzysztof Zdziarski }
120266b0663SKrzysztof Zdziarski
121266b0663SKrzysztof Zdziarski return 0;
122266b0663SKrzysztof Zdziarski }
123266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_get_num_devices(unsigned int cmd,caddr_t arg)124266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_get_num_devices(unsigned int cmd,
125266b0663SKrzysztof Zdziarski caddr_t arg)
126266b0663SKrzysztof Zdziarski {
127266b0663SKrzysztof Zdziarski adf_devmgr_get_num_dev((uint32_t *)arg);
128266b0663SKrzysztof Zdziarski
129266b0663SKrzysztof Zdziarski return 0;
130266b0663SKrzysztof Zdziarski }
131266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_get_status(unsigned int cmd,caddr_t arg)132266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_get_status(unsigned int cmd,
133266b0663SKrzysztof Zdziarski caddr_t arg)
134266b0663SKrzysztof Zdziarski {
135266b0663SKrzysztof Zdziarski struct adf_hw_device_data *hw_data;
136266b0663SKrzysztof Zdziarski struct adf_dev_status_info *dev_info;
137266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev;
138266b0663SKrzysztof Zdziarski
139266b0663SKrzysztof Zdziarski dev_info = (struct adf_dev_status_info *)arg;
140266b0663SKrzysztof Zdziarski
141266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(dev_info->accel_id);
142266b0663SKrzysztof Zdziarski if (!accel_dev)
143266b0663SKrzysztof Zdziarski return ENODEV;
144266b0663SKrzysztof Zdziarski
145266b0663SKrzysztof Zdziarski hw_data = accel_dev->hw_device;
146266b0663SKrzysztof Zdziarski dev_info->state = adf_dev_started(accel_dev) ? DEV_UP : DEV_DOWN;
147266b0663SKrzysztof Zdziarski dev_info->num_ae = hw_data->get_num_aes(hw_data);
148266b0663SKrzysztof Zdziarski dev_info->num_accel = hw_data->get_num_accels(hw_data);
149266b0663SKrzysztof Zdziarski dev_info->num_logical_accel = hw_data->num_logical_accel;
150266b0663SKrzysztof Zdziarski dev_info->banks_per_accel = hw_data->num_banks
151266b0663SKrzysztof Zdziarski / hw_data->num_logical_accel;
152266b0663SKrzysztof Zdziarski strlcpy(dev_info->name, hw_data->dev_class->name,
153266b0663SKrzysztof Zdziarski sizeof(dev_info->name));
154266b0663SKrzysztof Zdziarski dev_info->instance_id = hw_data->instance_id;
155266b0663SKrzysztof Zdziarski dev_info->type = hw_data->dev_class->type;
156266b0663SKrzysztof Zdziarski dev_info->bus = pci_get_bus(accel_to_pci_dev(accel_dev));
157266b0663SKrzysztof Zdziarski dev_info->dev = pci_get_slot(accel_to_pci_dev(accel_dev));
158266b0663SKrzysztof Zdziarski dev_info->fun = pci_get_function(accel_to_pci_dev(accel_dev));
159266b0663SKrzysztof Zdziarski dev_info->domain = pci_get_domain(accel_to_pci_dev(accel_dev));
160266b0663SKrzysztof Zdziarski
161266b0663SKrzysztof Zdziarski dev_info->pci_device_id = pci_get_device(accel_to_pci_dev(accel_dev));
162266b0663SKrzysztof Zdziarski
163266b0663SKrzysztof Zdziarski dev_info->node_id = accel_dev->accel_pci_dev.node;
164266b0663SKrzysztof Zdziarski dev_info->sku = accel_dev->accel_pci_dev.sku;
165266b0663SKrzysztof Zdziarski
166266b0663SKrzysztof Zdziarski dev_info->device_mem_available = accel_dev->aram_info ?
167266b0663SKrzysztof Zdziarski accel_dev->aram_info->inter_buff_aram_region_size : 0;
168266b0663SKrzysztof Zdziarski
169266b0663SKrzysztof Zdziarski return 0;
170266b0663SKrzysztof Zdziarski }
171266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_heartbeat(unsigned int cmd,caddr_t arg)172266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_heartbeat(unsigned int cmd,
173266b0663SKrzysztof Zdziarski caddr_t arg)
174266b0663SKrzysztof Zdziarski {
175266b0663SKrzysztof Zdziarski int ret = 0;
176266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev;
177266b0663SKrzysztof Zdziarski struct adf_dev_heartbeat_status_ctl *hb_status;
178266b0663SKrzysztof Zdziarski
179266b0663SKrzysztof Zdziarski hb_status = (struct adf_dev_heartbeat_status_ctl *)arg;
180266b0663SKrzysztof Zdziarski
181266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(hb_status->device_id);
182266b0663SKrzysztof Zdziarski if (!accel_dev)
183266b0663SKrzysztof Zdziarski return ENODEV;
184266b0663SKrzysztof Zdziarski
185266b0663SKrzysztof Zdziarski if (adf_heartbeat_status(accel_dev, &hb_status->status)) {
186266b0663SKrzysztof Zdziarski device_printf(GET_DEV(accel_dev),
187266b0663SKrzysztof Zdziarski "failed to get heartbeat status\n");
188266b0663SKrzysztof Zdziarski return EAGAIN;
189266b0663SKrzysztof Zdziarski }
190266b0663SKrzysztof Zdziarski return ret;
191266b0663SKrzysztof Zdziarski }
192266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_dev_get_value(unsigned int cmd,caddr_t arg)193266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_dev_get_value(unsigned int cmd,
194266b0663SKrzysztof Zdziarski caddr_t arg)
195266b0663SKrzysztof Zdziarski {
196266b0663SKrzysztof Zdziarski int ret = 0;
197266b0663SKrzysztof Zdziarski struct adf_user_cfg_ctl_data *ctl_data;
198266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev;
199266b0663SKrzysztof Zdziarski
200266b0663SKrzysztof Zdziarski ret = adf_ctl_alloc_resources(&ctl_data, arg);
201266b0663SKrzysztof Zdziarski if (ret)
202266b0663SKrzysztof Zdziarski return ret;
203266b0663SKrzysztof Zdziarski
204266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
205266b0663SKrzysztof Zdziarski if (!accel_dev) {
206266b0663SKrzysztof Zdziarski printf("QAT: Device %d not found\n", ctl_data->device_id);
207266b0663SKrzysztof Zdziarski ret = ENODEV;
208266b0663SKrzysztof Zdziarski goto out;
209266b0663SKrzysztof Zdziarski }
210266b0663SKrzysztof Zdziarski
211266b0663SKrzysztof Zdziarski ret = adf_copy_keyval_to_user(accel_dev, ctl_data);
212266b0663SKrzysztof Zdziarski if (ret) {
213266b0663SKrzysztof Zdziarski ret = ENODEV;
214266b0663SKrzysztof Zdziarski goto out;
215266b0663SKrzysztof Zdziarski }
216266b0663SKrzysztof Zdziarski out:
217266b0663SKrzysztof Zdziarski return ret;
218266b0663SKrzysztof Zdziarski }
219266b0663SKrzysztof Zdziarski
220266b0663SKrzysztof Zdziarski static struct adf_uio_control_bundle
adf_ctl_ioctl_bundle(struct adf_user_reserve_ring reserve)221266b0663SKrzysztof Zdziarski *adf_ctl_ioctl_bundle(struct adf_user_reserve_ring reserve)
222266b0663SKrzysztof Zdziarski {
223266b0663SKrzysztof Zdziarski struct adf_accel_dev *accel_dev;
224266b0663SKrzysztof Zdziarski struct adf_uio_control_accel *accel;
225266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle = NULL;
226266b0663SKrzysztof Zdziarski u8 num_rings_per_bank = 0;
227266b0663SKrzysztof Zdziarski
228266b0663SKrzysztof Zdziarski accel_dev = adf_devmgr_get_dev_by_id(reserve.accel_id);
229266b0663SKrzysztof Zdziarski if (!accel_dev) {
230266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get accel_dev\n");
231266b0663SKrzysztof Zdziarski return NULL;
232266b0663SKrzysztof Zdziarski }
233266b0663SKrzysztof Zdziarski num_rings_per_bank = accel_dev->hw_device->num_rings_per_bank;
234266b0663SKrzysztof Zdziarski
235266b0663SKrzysztof Zdziarski accel = accel_dev->accel;
236266b0663SKrzysztof Zdziarski if (!accel) {
237266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get accel\n");
238266b0663SKrzysztof Zdziarski return NULL;
239266b0663SKrzysztof Zdziarski }
240266b0663SKrzysztof Zdziarski
241266b0663SKrzysztof Zdziarski if (reserve.bank_nr >= GET_MAX_BANKS(accel_dev)) {
242266b0663SKrzysztof Zdziarski pr_err("QAT: Invalid bank number %d\n", reserve.bank_nr);
243266b0663SKrzysztof Zdziarski return NULL;
244266b0663SKrzysztof Zdziarski }
245266b0663SKrzysztof Zdziarski if (reserve.ring_mask & ~((1 << num_rings_per_bank) - 1)) {
246266b0663SKrzysztof Zdziarski pr_err("QAT: Invalid ring mask %0X\n", reserve.ring_mask);
247266b0663SKrzysztof Zdziarski return NULL;
248266b0663SKrzysztof Zdziarski }
249266b0663SKrzysztof Zdziarski if (accel->num_ker_bundles > reserve.bank_nr) {
250266b0663SKrzysztof Zdziarski pr_err("QAT: Invalid user reserved bank\n");
251266b0663SKrzysztof Zdziarski return NULL;
252266b0663SKrzysztof Zdziarski }
253266b0663SKrzysztof Zdziarski bundle = &accel->bundle[reserve.bank_nr];
254266b0663SKrzysztof Zdziarski
255266b0663SKrzysztof Zdziarski return bundle;
256266b0663SKrzysztof Zdziarski }
257266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_reserve_ring(caddr_t arg)258266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_reserve_ring(caddr_t arg)
259266b0663SKrzysztof Zdziarski {
260266b0663SKrzysztof Zdziarski struct adf_user_reserve_ring reserve = {0};
261266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
262266b0663SKrzysztof Zdziarski struct adf_uio_instance_rings *instance_rings;
263266b0663SKrzysztof Zdziarski int pid_entry_found = 0;
264266b0663SKrzysztof Zdziarski
265266b0663SKrzysztof Zdziarski reserve = *((struct adf_user_reserve_ring *)arg);
266266b0663SKrzysztof Zdziarski
267266b0663SKrzysztof Zdziarski bundle = adf_ctl_ioctl_bundle(reserve);
268266b0663SKrzysztof Zdziarski if (!bundle) {
269266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get bundle\n");
270266b0663SKrzysztof Zdziarski return -EINVAL;
271266b0663SKrzysztof Zdziarski }
272266b0663SKrzysztof Zdziarski
273266b0663SKrzysztof Zdziarski mutex_lock(&bundle->lock);
274266b0663SKrzysztof Zdziarski if (bundle->rings_used & reserve.ring_mask) {
275266b0663SKrzysztof Zdziarski pr_err("QAT: Bundle %d, rings 0x%04X already reserved\n",
276266b0663SKrzysztof Zdziarski reserve.bank_nr,
277266b0663SKrzysztof Zdziarski reserve.ring_mask);
278266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->lock);
279266b0663SKrzysztof Zdziarski return -EINVAL;
280266b0663SKrzysztof Zdziarski }
281266b0663SKrzysztof Zdziarski
282266b0663SKrzysztof Zdziarski /* Find the list entry for this process */
283266b0663SKrzysztof Zdziarski mutex_lock(&bundle->list_lock);
284266b0663SKrzysztof Zdziarski list_for_each_entry(instance_rings, &bundle->list, list) {
285266b0663SKrzysztof Zdziarski if (instance_rings->user_pid == curproc->p_pid) {
286266b0663SKrzysztof Zdziarski pid_entry_found = 1;
287266b0663SKrzysztof Zdziarski break;
288266b0663SKrzysztof Zdziarski }
289266b0663SKrzysztof Zdziarski }
290266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->list_lock);
291266b0663SKrzysztof Zdziarski
292266b0663SKrzysztof Zdziarski if (!pid_entry_found) {
293266b0663SKrzysztof Zdziarski pr_err("QAT: process %d not found\n", curproc->p_pid);
294*22cf89c9SPiotr Kasierski mutex_unlock(&bundle->lock);
295266b0663SKrzysztof Zdziarski return -EINVAL;
296266b0663SKrzysztof Zdziarski }
297266b0663SKrzysztof Zdziarski
298266b0663SKrzysztof Zdziarski instance_rings->ring_mask |= reserve.ring_mask;
299266b0663SKrzysztof Zdziarski bundle->rings_used |= reserve.ring_mask;
300266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->lock);
301266b0663SKrzysztof Zdziarski
302266b0663SKrzysztof Zdziarski return 0;
303266b0663SKrzysztof Zdziarski }
304266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_release_ring(caddr_t arg)305266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_release_ring(caddr_t arg)
306266b0663SKrzysztof Zdziarski {
307266b0663SKrzysztof Zdziarski struct adf_user_reserve_ring reserve;
308266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
309266b0663SKrzysztof Zdziarski struct adf_uio_instance_rings *instance_rings;
310266b0663SKrzysztof Zdziarski int pid_entry_found;
311266b0663SKrzysztof Zdziarski
312266b0663SKrzysztof Zdziarski reserve = *((struct adf_user_reserve_ring *)arg);
313266b0663SKrzysztof Zdziarski
314266b0663SKrzysztof Zdziarski bundle = adf_ctl_ioctl_bundle(reserve);
315266b0663SKrzysztof Zdziarski if (!bundle) {
316266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get bundle\n");
317266b0663SKrzysztof Zdziarski return -EINVAL;
318266b0663SKrzysztof Zdziarski }
319266b0663SKrzysztof Zdziarski
320266b0663SKrzysztof Zdziarski /* Find the list entry for this process */
321266b0663SKrzysztof Zdziarski pid_entry_found = 0;
322266b0663SKrzysztof Zdziarski mutex_lock(&bundle->list_lock);
323266b0663SKrzysztof Zdziarski list_for_each_entry(instance_rings, &bundle->list, list) {
324266b0663SKrzysztof Zdziarski if (instance_rings->user_pid == curproc->p_pid) {
325266b0663SKrzysztof Zdziarski pid_entry_found = 1;
326266b0663SKrzysztof Zdziarski break;
327266b0663SKrzysztof Zdziarski }
328266b0663SKrzysztof Zdziarski }
329266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->list_lock);
330266b0663SKrzysztof Zdziarski
331266b0663SKrzysztof Zdziarski if (!pid_entry_found) {
332266b0663SKrzysztof Zdziarski pr_err("QAT: No ring reservation found for PID %d\n",
333266b0663SKrzysztof Zdziarski curproc->p_pid);
334266b0663SKrzysztof Zdziarski return -EINVAL;
335266b0663SKrzysztof Zdziarski }
336266b0663SKrzysztof Zdziarski
337266b0663SKrzysztof Zdziarski if ((instance_rings->ring_mask & reserve.ring_mask) !=
338266b0663SKrzysztof Zdziarski reserve.ring_mask) {
339266b0663SKrzysztof Zdziarski pr_err("QAT: Attempt to release rings not reserved by this process\n");
340266b0663SKrzysztof Zdziarski return -EINVAL;
341266b0663SKrzysztof Zdziarski }
342266b0663SKrzysztof Zdziarski
343266b0663SKrzysztof Zdziarski instance_rings->ring_mask &= ~reserve.ring_mask;
344266b0663SKrzysztof Zdziarski mutex_lock(&bundle->lock);
345266b0663SKrzysztof Zdziarski bundle->rings_used &= ~reserve.ring_mask;
346266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->lock);
347266b0663SKrzysztof Zdziarski
348266b0663SKrzysztof Zdziarski return 0;
349266b0663SKrzysztof Zdziarski }
350266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_enable_ring(caddr_t arg)351266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_enable_ring(caddr_t arg)
352266b0663SKrzysztof Zdziarski {
353266b0663SKrzysztof Zdziarski struct adf_user_reserve_ring reserve;
354266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
355266b0663SKrzysztof Zdziarski
356266b0663SKrzysztof Zdziarski reserve = *((struct adf_user_reserve_ring *)arg);
357266b0663SKrzysztof Zdziarski
358266b0663SKrzysztof Zdziarski bundle = adf_ctl_ioctl_bundle(reserve);
359266b0663SKrzysztof Zdziarski if (!bundle) {
360266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get bundle\n");
361266b0663SKrzysztof Zdziarski return -EINVAL;
362266b0663SKrzysztof Zdziarski }
363266b0663SKrzysztof Zdziarski
364266b0663SKrzysztof Zdziarski mutex_lock(&bundle->lock);
365266b0663SKrzysztof Zdziarski bundle->rings_enabled |= reserve.ring_mask;
366266b0663SKrzysztof Zdziarski adf_update_uio_ring_arb(bundle);
367266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->lock);
368266b0663SKrzysztof Zdziarski
369266b0663SKrzysztof Zdziarski return 0;
370266b0663SKrzysztof Zdziarski }
371266b0663SKrzysztof Zdziarski
adf_ctl_ioctl_disable_ring(caddr_t arg)372266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl_disable_ring(caddr_t arg)
373266b0663SKrzysztof Zdziarski {
374266b0663SKrzysztof Zdziarski struct adf_user_reserve_ring reserve;
375266b0663SKrzysztof Zdziarski struct adf_uio_control_bundle *bundle;
376266b0663SKrzysztof Zdziarski
377266b0663SKrzysztof Zdziarski reserve = *((struct adf_user_reserve_ring *)arg);
378266b0663SKrzysztof Zdziarski
379266b0663SKrzysztof Zdziarski bundle = adf_ctl_ioctl_bundle(reserve);
380266b0663SKrzysztof Zdziarski if (!bundle) {
381266b0663SKrzysztof Zdziarski pr_err("QAT: Failed to get bundle\n");
382266b0663SKrzysztof Zdziarski return -EINVAL;
383266b0663SKrzysztof Zdziarski }
384266b0663SKrzysztof Zdziarski
385266b0663SKrzysztof Zdziarski mutex_lock(&bundle->lock);
386266b0663SKrzysztof Zdziarski bundle->rings_enabled &= ~reserve.ring_mask;
387266b0663SKrzysztof Zdziarski adf_update_uio_ring_arb(bundle);
388266b0663SKrzysztof Zdziarski mutex_unlock(&bundle->lock);
389266b0663SKrzysztof Zdziarski
390266b0663SKrzysztof Zdziarski return 0;
391266b0663SKrzysztof Zdziarski }
392266b0663SKrzysztof Zdziarski
adf_ctl_ioctl(struct cdev * dev,u_long cmd,caddr_t arg,int fflag,struct thread * td)393266b0663SKrzysztof Zdziarski static int adf_ctl_ioctl(struct cdev *dev,
394266b0663SKrzysztof Zdziarski u_long cmd,
395266b0663SKrzysztof Zdziarski caddr_t arg,
396266b0663SKrzysztof Zdziarski int fflag,
397266b0663SKrzysztof Zdziarski struct thread *td)
398266b0663SKrzysztof Zdziarski {
399266b0663SKrzysztof Zdziarski int ret = 0;
400266b0663SKrzysztof Zdziarski bool allowed = false;
401266b0663SKrzysztof Zdziarski int i;
402266b0663SKrzysztof Zdziarski static const unsigned int unrestricted_cmds[] = {
403266b0663SKrzysztof Zdziarski IOCTL_GET_NUM_DEVICES, IOCTL_STATUS_ACCEL_DEV,
404266b0663SKrzysztof Zdziarski IOCTL_HEARTBEAT_ACCEL_DEV, IOCTL_GET_CFG_VAL,
405266b0663SKrzysztof Zdziarski IOCTL_RESERVE_RING, IOCTL_RELEASE_RING,
406266b0663SKrzysztof Zdziarski IOCTL_ENABLE_RING, IOCTL_DISABLE_RING,
407266b0663SKrzysztof Zdziarski };
408266b0663SKrzysztof Zdziarski
409266b0663SKrzysztof Zdziarski if (priv_check(curthread, PRIV_DRIVER)) {
410266b0663SKrzysztof Zdziarski for (i = 0; i < ARRAY_SIZE(unrestricted_cmds); i++) {
411266b0663SKrzysztof Zdziarski if (cmd == unrestricted_cmds[i]) {
412266b0663SKrzysztof Zdziarski allowed = true;
413266b0663SKrzysztof Zdziarski break;
414266b0663SKrzysztof Zdziarski }
415266b0663SKrzysztof Zdziarski }
416266b0663SKrzysztof Zdziarski if (!allowed)
417266b0663SKrzysztof Zdziarski return EACCES;
418266b0663SKrzysztof Zdziarski }
419266b0663SKrzysztof Zdziarski
420266b0663SKrzysztof Zdziarski /* All commands have an argument */
421266b0663SKrzysztof Zdziarski if (!arg)
422266b0663SKrzysztof Zdziarski return EFAULT;
423266b0663SKrzysztof Zdziarski
424266b0663SKrzysztof Zdziarski if (sx_xlock_sig(&adf_ctl_lock))
425266b0663SKrzysztof Zdziarski return EINTR;
426266b0663SKrzysztof Zdziarski
427266b0663SKrzysztof Zdziarski switch (cmd) {
428266b0663SKrzysztof Zdziarski case IOCTL_GET_NUM_DEVICES:
429266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_get_num_devices(cmd, arg);
430266b0663SKrzysztof Zdziarski break;
431266b0663SKrzysztof Zdziarski case IOCTL_STATUS_ACCEL_DEV:
432266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_get_status(cmd, arg);
433266b0663SKrzysztof Zdziarski break;
434266b0663SKrzysztof Zdziarski case IOCTL_GET_CFG_VAL:
435266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_dev_get_value(cmd, arg);
436266b0663SKrzysztof Zdziarski break;
437266b0663SKrzysztof Zdziarski case IOCTL_RESERVE_RING:
438266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_reserve_ring(arg);
439266b0663SKrzysztof Zdziarski break;
440266b0663SKrzysztof Zdziarski case IOCTL_RELEASE_RING:
441266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_release_ring(arg);
442266b0663SKrzysztof Zdziarski break;
443266b0663SKrzysztof Zdziarski case IOCTL_ENABLE_RING:
444266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_enable_ring(arg);
445266b0663SKrzysztof Zdziarski break;
446266b0663SKrzysztof Zdziarski case IOCTL_DISABLE_RING:
447266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_disable_ring(arg);
448266b0663SKrzysztof Zdziarski break;
449266b0663SKrzysztof Zdziarski case IOCTL_HEARTBEAT_ACCEL_DEV:
450266b0663SKrzysztof Zdziarski ret = adf_ctl_ioctl_heartbeat(cmd, arg);
451266b0663SKrzysztof Zdziarski break;
452266b0663SKrzysztof Zdziarski default:
453266b0663SKrzysztof Zdziarski printf("QAT: Invalid ioctl\n");
454266b0663SKrzysztof Zdziarski ret = ENOTTY;
455266b0663SKrzysztof Zdziarski break;
456266b0663SKrzysztof Zdziarski }
457266b0663SKrzysztof Zdziarski sx_xunlock(&adf_ctl_lock);
458266b0663SKrzysztof Zdziarski return ret;
459266b0663SKrzysztof Zdziarski }
460266b0663SKrzysztof Zdziarski
461266b0663SKrzysztof Zdziarski int
adf_register_ctl_device_driver(void)462266b0663SKrzysztof Zdziarski adf_register_ctl_device_driver(void)
463266b0663SKrzysztof Zdziarski {
464266b0663SKrzysztof Zdziarski sx_init(&adf_ctl_lock, "adf ctl");
465266b0663SKrzysztof Zdziarski
466266b0663SKrzysztof Zdziarski if (adf_chr_drv_create())
467266b0663SKrzysztof Zdziarski goto err_chr_dev;
468266b0663SKrzysztof Zdziarski
469266b0663SKrzysztof Zdziarski adf_state_init();
470266b0663SKrzysztof Zdziarski if (adf_processes_dev_register() != 0)
471266b0663SKrzysztof Zdziarski goto err_processes_dev_register;
472266b0663SKrzysztof Zdziarski return 0;
473266b0663SKrzysztof Zdziarski
474266b0663SKrzysztof Zdziarski err_processes_dev_register:
475266b0663SKrzysztof Zdziarski adf_chr_drv_destroy();
476266b0663SKrzysztof Zdziarski err_chr_dev:
477266b0663SKrzysztof Zdziarski sx_destroy(&adf_ctl_lock);
478266b0663SKrzysztof Zdziarski return EFAULT;
479266b0663SKrzysztof Zdziarski }
480266b0663SKrzysztof Zdziarski
481266b0663SKrzysztof Zdziarski void
adf_unregister_ctl_device_driver(void)482266b0663SKrzysztof Zdziarski adf_unregister_ctl_device_driver(void)
483266b0663SKrzysztof Zdziarski {
484266b0663SKrzysztof Zdziarski adf_processes_dev_unregister();
485266b0663SKrzysztof Zdziarski adf_state_destroy();
486266b0663SKrzysztof Zdziarski adf_chr_drv_destroy();
487266b0663SKrzysztof Zdziarski adf_clean_vf_map(false);
488266b0663SKrzysztof Zdziarski sx_destroy(&adf_ctl_lock);
489266b0663SKrzysztof Zdziarski }
490