xref: /freebsd/sys/dev/qat/qat_common/adf_freebsd_uio.c (revision 866dc4bd81398b478daefe4b7447b92422b4a06c)
1*266b0663SKrzysztof Zdziarski /* SPDX-License-Identifier: BSD-3-Clause */
2*266b0663SKrzysztof Zdziarski /* Copyright(c) 2007-2022 Intel Corporation */
3*266b0663SKrzysztof Zdziarski #include "qat_freebsd.h"
4*266b0663SKrzysztof Zdziarski #include "adf_cfg.h"
5*266b0663SKrzysztof Zdziarski #include "adf_common_drv.h"
6*266b0663SKrzysztof Zdziarski #include "adf_accel_devices.h"
7*266b0663SKrzysztof Zdziarski #include "icp_qat_uclo.h"
8*266b0663SKrzysztof Zdziarski #include "icp_qat_fw.h"
9*266b0663SKrzysztof Zdziarski #include "icp_qat_fw_init_admin.h"
10*266b0663SKrzysztof Zdziarski #include "adf_cfg_strings.h"
11*266b0663SKrzysztof Zdziarski #include "adf_uio_control.h"
12*266b0663SKrzysztof Zdziarski #include "adf_uio_cleanup.h"
13*266b0663SKrzysztof Zdziarski #include "adf_uio.h"
14*266b0663SKrzysztof Zdziarski #include "adf_transport_access_macros.h"
15*266b0663SKrzysztof Zdziarski #include "adf_transport_internal.h"
16*266b0663SKrzysztof Zdziarski #include <sys/conf.h>
17*266b0663SKrzysztof Zdziarski #include <sys/capsicum.h>
18*266b0663SKrzysztof Zdziarski #include <sys/kdb.h>
19*266b0663SKrzysztof Zdziarski #include <sys/condvar.h>
20*266b0663SKrzysztof Zdziarski #include <sys/param.h>
21*266b0663SKrzysztof Zdziarski #include <sys/systm.h>
22*266b0663SKrzysztof Zdziarski #include <sys/proc.h>
23*266b0663SKrzysztof Zdziarski #include <sys/file.h>
24*266b0663SKrzysztof Zdziarski #include <sys/lock.h>
25*266b0663SKrzysztof Zdziarski #include <sys/rwlock.h>
26*266b0663SKrzysztof Zdziarski #include <sys/sglist.h>
27*266b0663SKrzysztof Zdziarski #include <vm/vm.h>
28*266b0663SKrzysztof Zdziarski #include <vm/vm_object.h>
29*266b0663SKrzysztof Zdziarski #include <vm/vm_page.h>
30*266b0663SKrzysztof Zdziarski #include <vm/vm_pager.h>
31*266b0663SKrzysztof Zdziarski 
32*266b0663SKrzysztof Zdziarski #define ADF_UIO_GET_NAME(accel_dev) (GET_HW_DATA(accel_dev)->dev_class->name)
33*266b0663SKrzysztof Zdziarski #define ADF_UIO_GET_TYPE(accel_dev) (GET_HW_DATA(accel_dev)->dev_class->type)
34*266b0663SKrzysztof Zdziarski #define ADF_UIO_GET_BAR(accel_dev)                                             \
35*266b0663SKrzysztof Zdziarski 	(GET_HW_DATA(accel_dev)->get_etr_bar_id(GET_HW_DATA(accel_dev)))
36*266b0663SKrzysztof Zdziarski 
37*266b0663SKrzysztof Zdziarski static d_ioctl_t adf_uio_ioctl;
38*266b0663SKrzysztof Zdziarski static d_mmap_single_t adf_uio_mmap_single;
39*266b0663SKrzysztof Zdziarski 
40*266b0663SKrzysztof Zdziarski static struct cdevsw adf_uio_cdevsw = { .d_ioctl = adf_uio_ioctl,
41*266b0663SKrzysztof Zdziarski 					.d_mmap_single = adf_uio_mmap_single,
42*266b0663SKrzysztof Zdziarski 					.d_version = D_VERSION,
43*266b0663SKrzysztof Zdziarski 					.d_name = "qat" };
44*266b0663SKrzysztof Zdziarski 
45*266b0663SKrzysztof Zdziarski struct adf_uio_open_bundle {
46*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel;
47*266b0663SKrzysztof Zdziarski 	int bundle;
48*266b0663SKrzysztof Zdziarski 	struct file **mem_files;
49*266b0663SKrzysztof Zdziarski 	int num_mem_files;
50*266b0663SKrzysztof Zdziarski };
51*266b0663SKrzysztof Zdziarski 
52*266b0663SKrzysztof Zdziarski static void
adf_release_bundle(void * arg)53*266b0663SKrzysztof Zdziarski adf_release_bundle(void *arg)
54*266b0663SKrzysztof Zdziarski {
55*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = NULL;
56*266b0663SKrzysztof Zdziarski 	struct adf_uio_open_bundle *handle = NULL;
57*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_bundle *bundle = NULL;
58*266b0663SKrzysztof Zdziarski 	struct adf_uio_instance_rings *instance_rings, *tmp;
59*266b0663SKrzysztof Zdziarski 	int i = 0;
60*266b0663SKrzysztof Zdziarski 
61*266b0663SKrzysztof Zdziarski 	handle = arg;
62*266b0663SKrzysztof Zdziarski 	accel = handle->accel;
63*266b0663SKrzysztof Zdziarski 	bundle = &accel->bundle[handle->bundle];
64*266b0663SKrzysztof Zdziarski 
65*266b0663SKrzysztof Zdziarski 	mutex_lock(&bundle->lock);
66*266b0663SKrzysztof Zdziarski 	adf_uio_do_cleanup_orphan(bundle->hardware_bundle_number, accel);
67*266b0663SKrzysztof Zdziarski 	mutex_unlock(&bundle->lock);
68*266b0663SKrzysztof Zdziarski 
69*266b0663SKrzysztof Zdziarski 	for (i = 0; i < handle->num_mem_files; i++) {
70*266b0663SKrzysztof Zdziarski 		/*
71*266b0663SKrzysztof Zdziarski 		 * Similar to the garbage collection of orphaned file
72*266b0663SKrzysztof Zdziarski 		 * descriptor references in UNIX domain socket control
73*266b0663SKrzysztof Zdziarski 		 * messages, the current thread isn't relevant to the
74*266b0663SKrzysztof Zdziarski 		 * the file descriptor reference being released.  In
75*266b0663SKrzysztof Zdziarski 		 * particular, the current thread does not hold any
76*266b0663SKrzysztof Zdziarski 		 * advisory file locks on these file descriptors.
77*266b0663SKrzysztof Zdziarski 		 */
78*266b0663SKrzysztof Zdziarski 		fdrop(handle->mem_files[i], NULL);
79*266b0663SKrzysztof Zdziarski 	}
80*266b0663SKrzysztof Zdziarski 	free(handle->mem_files, M_QAT);
81*266b0663SKrzysztof Zdziarski 
82*266b0663SKrzysztof Zdziarski 	mtx_lock(&accel->lock);
83*266b0663SKrzysztof Zdziarski 
84*266b0663SKrzysztof Zdziarski 	mutex_lock(&bundle->list_lock);
85*266b0663SKrzysztof Zdziarski 	list_for_each_entry_safe(instance_rings, tmp, &bundle->list, list)
86*266b0663SKrzysztof Zdziarski 	{
87*266b0663SKrzysztof Zdziarski 		if (instance_rings->user_pid == curproc->p_pid) {
88*266b0663SKrzysztof Zdziarski 			list_del(&instance_rings->list);
89*266b0663SKrzysztof Zdziarski 			free(instance_rings, M_QAT);
90*266b0663SKrzysztof Zdziarski 			break;
91*266b0663SKrzysztof Zdziarski 		}
92*266b0663SKrzysztof Zdziarski 	}
93*266b0663SKrzysztof Zdziarski 	mutex_unlock(&bundle->list_lock);
94*266b0663SKrzysztof Zdziarski 
95*266b0663SKrzysztof Zdziarski 	adf_dev_put(accel->accel_dev);
96*266b0663SKrzysztof Zdziarski 	accel->num_handles--;
97*266b0663SKrzysztof Zdziarski 	free(handle, M_QAT);
98*266b0663SKrzysztof Zdziarski 	if (!accel->num_handles) {
99*266b0663SKrzysztof Zdziarski 		cv_broadcast(&accel->cleanup_ok);
100*266b0663SKrzysztof Zdziarski 		/* the broadcasting effect happens after releasing accel->lock
101*266b0663SKrzysztof Zdziarski 		 */
102*266b0663SKrzysztof Zdziarski 	}
103*266b0663SKrzysztof Zdziarski 	mtx_unlock(&accel->lock);
104*266b0663SKrzysztof Zdziarski }
105*266b0663SKrzysztof Zdziarski 
106*266b0663SKrzysztof Zdziarski static int
adf_add_mem_fd(struct adf_accel_dev * accel_dev,int mem_fd)107*266b0663SKrzysztof Zdziarski adf_add_mem_fd(struct adf_accel_dev *accel_dev, int mem_fd)
108*266b0663SKrzysztof Zdziarski {
109*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = NULL;
110*266b0663SKrzysztof Zdziarski 	struct adf_uio_open_bundle *handle = NULL;
111*266b0663SKrzysztof Zdziarski 	struct file *fp, **new_files;
112*266b0663SKrzysztof Zdziarski 	cap_rights_t rights;
113*266b0663SKrzysztof Zdziarski 	int error = -1, old_count = 0;
114*266b0663SKrzysztof Zdziarski 
115*266b0663SKrzysztof Zdziarski 	error = devfs_get_cdevpriv((void **)&handle);
116*266b0663SKrzysztof Zdziarski 	if (error)
117*266b0663SKrzysztof Zdziarski 		return (error);
118*266b0663SKrzysztof Zdziarski 
119*266b0663SKrzysztof Zdziarski 	error = fget(curthread, mem_fd, cap_rights_init(&rights), &fp);
120*266b0663SKrzysztof Zdziarski 	if (error) {
121*266b0663SKrzysztof Zdziarski 		printf(
122*266b0663SKrzysztof Zdziarski 		    "Failed to fetch file pointer from current process %d \n",
123*266b0663SKrzysztof Zdziarski 		    __LINE__);
124*266b0663SKrzysztof Zdziarski 		return (error);
125*266b0663SKrzysztof Zdziarski 	}
126*266b0663SKrzysztof Zdziarski 
127*266b0663SKrzysztof Zdziarski 	accel = accel_dev->accel;
128*266b0663SKrzysztof Zdziarski 	mtx_lock(&accel->lock);
129*266b0663SKrzysztof Zdziarski 	for (;;) {
130*266b0663SKrzysztof Zdziarski 		old_count = handle->num_mem_files;
131*266b0663SKrzysztof Zdziarski 		mtx_unlock(&accel->lock);
132*266b0663SKrzysztof Zdziarski 		new_files = malloc((old_count + 1) * sizeof(*new_files),
133*266b0663SKrzysztof Zdziarski 				   M_QAT,
134*266b0663SKrzysztof Zdziarski 				   M_WAITOK);
135*266b0663SKrzysztof Zdziarski 		mtx_lock(&accel->lock);
136*266b0663SKrzysztof Zdziarski 		if (old_count == handle->num_mem_files) {
137*266b0663SKrzysztof Zdziarski 			if (old_count != 0) {
138*266b0663SKrzysztof Zdziarski 				memcpy(new_files,
139*266b0663SKrzysztof Zdziarski 				       handle->mem_files,
140*266b0663SKrzysztof Zdziarski 				       old_count * sizeof(*new_files));
141*266b0663SKrzysztof Zdziarski 				free(handle->mem_files, M_QAT);
142*266b0663SKrzysztof Zdziarski 			}
143*266b0663SKrzysztof Zdziarski 			handle->mem_files = new_files;
144*266b0663SKrzysztof Zdziarski 			new_files[old_count] = fp;
145*266b0663SKrzysztof Zdziarski 			handle->num_mem_files++;
146*266b0663SKrzysztof Zdziarski 			break;
147*266b0663SKrzysztof Zdziarski 		} else
148*266b0663SKrzysztof Zdziarski 			free(new_files, M_QAT);
149*266b0663SKrzysztof Zdziarski 	}
150*266b0663SKrzysztof Zdziarski 	mtx_unlock(&accel->lock);
151*266b0663SKrzysztof Zdziarski 	return (0);
152*266b0663SKrzysztof Zdziarski }
153*266b0663SKrzysztof Zdziarski 
154*266b0663SKrzysztof Zdziarski static vm_object_t
adf_uio_map_bar(struct adf_accel_dev * accel_dev,uint8_t bank_offset)155*266b0663SKrzysztof Zdziarski adf_uio_map_bar(struct adf_accel_dev *accel_dev, uint8_t bank_offset)
156*266b0663SKrzysztof Zdziarski {
157*266b0663SKrzysztof Zdziarski 	unsigned int ring_bundle_size, offset;
158*266b0663SKrzysztof Zdziarski 	struct sglist *sg = NULL;
159*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = accel_dev->accel;
160*266b0663SKrzysztof Zdziarski 	struct adf_hw_csr_info *csr_info = &accel_dev->hw_device->csr_info;
161*266b0663SKrzysztof Zdziarski 	vm_object_t obj;
162*266b0663SKrzysztof Zdziarski 
163*266b0663SKrzysztof Zdziarski 	ring_bundle_size = csr_info->ring_bundle_size;
164*266b0663SKrzysztof Zdziarski 	offset = bank_offset * ring_bundle_size;
165*266b0663SKrzysztof Zdziarski 
166*266b0663SKrzysztof Zdziarski 	sg = sglist_alloc(1, M_WAITOK);
167*266b0663SKrzysztof Zdziarski 
168*266b0663SKrzysztof Zdziarski 	/* Starting from new HW there is an additional offset
169*266b0663SKrzysztof Zdziarski 	 * for bundle CSRs
170*266b0663SKrzysztof Zdziarski 	 */
171*266b0663SKrzysztof Zdziarski 	sglist_append_phys(sg,
172*266b0663SKrzysztof Zdziarski 			   accel->bar->base_addr + offset +
173*266b0663SKrzysztof Zdziarski 			       csr_info->csr_addr_offset,
174*266b0663SKrzysztof Zdziarski 			   ring_bundle_size);
175*266b0663SKrzysztof Zdziarski 
176*266b0663SKrzysztof Zdziarski 	obj = vm_pager_allocate(
177*266b0663SKrzysztof Zdziarski 	    OBJT_SG, sg, ring_bundle_size, VM_PROT_RW, 0, NULL);
178*266b0663SKrzysztof Zdziarski 	if (obj != NULL) {
179*266b0663SKrzysztof Zdziarski 		VM_OBJECT_WLOCK(obj);
180*266b0663SKrzysztof Zdziarski 		vm_object_set_memattr(obj, VM_MEMATTR_UNCACHEABLE);
181*266b0663SKrzysztof Zdziarski 		VM_OBJECT_WUNLOCK(obj);
182*266b0663SKrzysztof Zdziarski 	}
183*266b0663SKrzysztof Zdziarski 	sglist_free(sg);
184*266b0663SKrzysztof Zdziarski 
185*266b0663SKrzysztof Zdziarski 	return obj;
186*266b0663SKrzysztof Zdziarski }
187*266b0663SKrzysztof Zdziarski 
188*266b0663SKrzysztof Zdziarski static int
adf_alloc_bundle(struct adf_accel_dev * accel_dev,int bundle_nr)189*266b0663SKrzysztof Zdziarski adf_alloc_bundle(struct adf_accel_dev *accel_dev, int bundle_nr)
190*266b0663SKrzysztof Zdziarski {
191*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = NULL;
192*266b0663SKrzysztof Zdziarski 	struct adf_uio_open_bundle *handle = NULL;
193*266b0663SKrzysztof Zdziarski 	int error;
194*266b0663SKrzysztof Zdziarski 
195*266b0663SKrzysztof Zdziarski 	if (bundle_nr < 0 || bundle_nr >= GET_MAX_BANKS(accel_dev)) {
196*266b0663SKrzysztof Zdziarski 		printf("ERROR in %s (%d) %d\n", __func__, bundle_nr, __LINE__);
197*266b0663SKrzysztof Zdziarski 		return EINVAL;
198*266b0663SKrzysztof Zdziarski 	}
199*266b0663SKrzysztof Zdziarski 
200*266b0663SKrzysztof Zdziarski 	accel = accel_dev->accel;
201*266b0663SKrzysztof Zdziarski 	handle = malloc(sizeof(*handle), M_QAT, M_WAITOK | M_ZERO);
202*266b0663SKrzysztof Zdziarski 	handle->accel = accel;
203*266b0663SKrzysztof Zdziarski 	handle->bundle = bundle_nr;
204*266b0663SKrzysztof Zdziarski 
205*266b0663SKrzysztof Zdziarski 	mtx_lock(&accel->lock);
206*266b0663SKrzysztof Zdziarski 	adf_dev_get(accel_dev);
207*266b0663SKrzysztof Zdziarski 	accel->num_handles++;
208*266b0663SKrzysztof Zdziarski 	mtx_unlock(&accel->lock);
209*266b0663SKrzysztof Zdziarski 
210*266b0663SKrzysztof Zdziarski 	error = devfs_set_cdevpriv(handle, adf_release_bundle);
211*266b0663SKrzysztof Zdziarski 	if (error) {
212*266b0663SKrzysztof Zdziarski 		adf_release_bundle(handle);
213*266b0663SKrzysztof Zdziarski 		device_printf(GET_DEV(accel_dev),
214*266b0663SKrzysztof Zdziarski 			      "ERROR in adf_alloc_bundle %d\n",
215*266b0663SKrzysztof Zdziarski 			      __LINE__);
216*266b0663SKrzysztof Zdziarski 		return (error);
217*266b0663SKrzysztof Zdziarski 	}
218*266b0663SKrzysztof Zdziarski 
219*266b0663SKrzysztof Zdziarski 	return (0);
220*266b0663SKrzysztof Zdziarski }
221*266b0663SKrzysztof Zdziarski 
222*266b0663SKrzysztof Zdziarski static int
adf_uio_ioctl(struct cdev * dev,u_long cmd,caddr_t data,int fflag,struct thread * td)223*266b0663SKrzysztof Zdziarski adf_uio_ioctl(struct cdev *dev,
224*266b0663SKrzysztof Zdziarski 	      u_long cmd,
225*266b0663SKrzysztof Zdziarski 	      caddr_t data,
226*266b0663SKrzysztof Zdziarski 	      int fflag,
227*266b0663SKrzysztof Zdziarski 	      struct thread *td)
228*266b0663SKrzysztof Zdziarski {
229*266b0663SKrzysztof Zdziarski 	struct adf_accel_dev *accel_dev = dev->si_drv1;
230*266b0663SKrzysztof Zdziarski 	struct adf_hw_csr_info *csr_info = NULL;
231*266b0663SKrzysztof Zdziarski 
232*266b0663SKrzysztof Zdziarski 	if (!accel_dev) {
233*266b0663SKrzysztof Zdziarski 		printf("%s - accel_dev is NULL\n", __func__);
234*266b0663SKrzysztof Zdziarski 		return EFAULT;
235*266b0663SKrzysztof Zdziarski 	}
236*266b0663SKrzysztof Zdziarski 
237*266b0663SKrzysztof Zdziarski 	csr_info = &accel_dev->hw_device->csr_info;
238*266b0663SKrzysztof Zdziarski 
239*266b0663SKrzysztof Zdziarski 	switch (cmd) {
240*266b0663SKrzysztof Zdziarski 	case IOCTL_GET_BUNDLE_SIZE:
241*266b0663SKrzysztof Zdziarski 		*(uint32_t *)data = csr_info->ring_bundle_size;
242*266b0663SKrzysztof Zdziarski 		break;
243*266b0663SKrzysztof Zdziarski 	case IOCTL_ALLOC_BUNDLE:
244*266b0663SKrzysztof Zdziarski 		return (adf_alloc_bundle(accel_dev, *(int *)data));
245*266b0663SKrzysztof Zdziarski 	case IOCTL_GET_ACCEL_TYPE:
246*266b0663SKrzysztof Zdziarski 		*(uint32_t *)data = ADF_UIO_GET_TYPE(accel_dev);
247*266b0663SKrzysztof Zdziarski 		break;
248*266b0663SKrzysztof Zdziarski 	case IOCTL_ADD_MEM_FD:
249*266b0663SKrzysztof Zdziarski 		return (adf_add_mem_fd(accel_dev, *(int *)data));
250*266b0663SKrzysztof Zdziarski 	default:
251*266b0663SKrzysztof Zdziarski 		return (ENOTTY);
252*266b0663SKrzysztof Zdziarski 	}
253*266b0663SKrzysztof Zdziarski 	return (0);
254*266b0663SKrzysztof Zdziarski }
255*266b0663SKrzysztof Zdziarski 
256*266b0663SKrzysztof Zdziarski static int
adf_uio_mmap_single(struct cdev * dev,vm_ooffset_t * offset,vm_size_t size,struct vm_object ** object,int nprot)257*266b0663SKrzysztof Zdziarski adf_uio_mmap_single(struct cdev *dev,
258*266b0663SKrzysztof Zdziarski 		    vm_ooffset_t *offset,
259*266b0663SKrzysztof Zdziarski 		    vm_size_t size,
260*266b0663SKrzysztof Zdziarski 		    struct vm_object **object,
261*266b0663SKrzysztof Zdziarski 		    int nprot)
262*266b0663SKrzysztof Zdziarski {
263*266b0663SKrzysztof Zdziarski 	struct adf_uio_open_bundle *handle = NULL;
264*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = NULL;
265*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_bundle *bundle = NULL;
266*266b0663SKrzysztof Zdziarski 	struct adf_uio_instance_rings *instance_rings;
267*266b0663SKrzysztof Zdziarski 	int error;
268*266b0663SKrzysztof Zdziarski 
269*266b0663SKrzysztof Zdziarski 	error = devfs_get_cdevpriv((void **)&handle);
270*266b0663SKrzysztof Zdziarski 	if (error)
271*266b0663SKrzysztof Zdziarski 		return (error);
272*266b0663SKrzysztof Zdziarski 
273*266b0663SKrzysztof Zdziarski 	if (!handle->accel) {
274*266b0663SKrzysztof Zdziarski 		printf("QAT: Error - no accel in handle\n");
275*266b0663SKrzysztof Zdziarski 		return EINVAL;
276*266b0663SKrzysztof Zdziarski 	}
277*266b0663SKrzysztof Zdziarski 	accel = handle->accel;
278*266b0663SKrzysztof Zdziarski 
279*266b0663SKrzysztof Zdziarski 	if (!accel->accel_dev) {
280*266b0663SKrzysztof Zdziarski 		printf("QAT: Error - no accel_dev in accel\n");
281*266b0663SKrzysztof Zdziarski 		return EINVAL;
282*266b0663SKrzysztof Zdziarski 	}
283*266b0663SKrzysztof Zdziarski 
284*266b0663SKrzysztof Zdziarski 	bundle = &accel->bundle[handle->bundle];
285*266b0663SKrzysztof Zdziarski 	if (!bundle->obj) {
286*266b0663SKrzysztof Zdziarski 		printf("QAT: Error no vm_object in bundle\n");
287*266b0663SKrzysztof Zdziarski 		return EINVAL;
288*266b0663SKrzysztof Zdziarski 	}
289*266b0663SKrzysztof Zdziarski 
290*266b0663SKrzysztof Zdziarski 	/* Adding pid to bundle list */
291*266b0663SKrzysztof Zdziarski 	instance_rings =
292*266b0663SKrzysztof Zdziarski 	    malloc(sizeof(*instance_rings), M_QAT, M_WAITOK | M_ZERO);
293*266b0663SKrzysztof Zdziarski 	instance_rings->user_pid = curproc->p_pid;
294*266b0663SKrzysztof Zdziarski 	instance_rings->ring_mask = 0;
295*266b0663SKrzysztof Zdziarski 	mutex_lock(&bundle->list_lock);
296*266b0663SKrzysztof Zdziarski 	list_add_tail(&instance_rings->list, &bundle->list);
297*266b0663SKrzysztof Zdziarski 	mutex_unlock(&bundle->list_lock);
298*266b0663SKrzysztof Zdziarski 
299*266b0663SKrzysztof Zdziarski 	vm_object_reference(bundle->obj);
300*266b0663SKrzysztof Zdziarski 	*object = bundle->obj;
301*266b0663SKrzysztof Zdziarski 	return (0);
302*266b0663SKrzysztof Zdziarski }
303*266b0663SKrzysztof Zdziarski 
304*266b0663SKrzysztof Zdziarski static inline void
adf_uio_init_accel_ctrl(struct adf_uio_control_accel * accel,struct adf_accel_dev * accel_dev,unsigned int nb_bundles)305*266b0663SKrzysztof Zdziarski adf_uio_init_accel_ctrl(struct adf_uio_control_accel *accel,
306*266b0663SKrzysztof Zdziarski 			struct adf_accel_dev *accel_dev,
307*266b0663SKrzysztof Zdziarski 			unsigned int nb_bundles)
308*266b0663SKrzysztof Zdziarski {
309*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_bundle *bundle;
310*266b0663SKrzysztof Zdziarski 	struct qat_uio_bundle_dev *priv;
311*266b0663SKrzysztof Zdziarski 	unsigned int i;
312*266b0663SKrzysztof Zdziarski 
313*266b0663SKrzysztof Zdziarski 	accel->nb_bundles = nb_bundles;
314*266b0663SKrzysztof Zdziarski 	accel->total_used_bundles = 0;
315*266b0663SKrzysztof Zdziarski 
316*266b0663SKrzysztof Zdziarski 	for (i = 0; i < nb_bundles; i++) {
317*266b0663SKrzysztof Zdziarski 		/*initialize the bundle */
318*266b0663SKrzysztof Zdziarski 		bundle = &accel->bundle[i];
319*266b0663SKrzysztof Zdziarski 		priv = &bundle->uio_priv;
320*266b0663SKrzysztof Zdziarski 		bundle->hardware_bundle_number =
321*266b0663SKrzysztof Zdziarski 		    GET_MAX_BANKS(accel_dev) - nb_bundles + i;
322*266b0663SKrzysztof Zdziarski 
323*266b0663SKrzysztof Zdziarski 		INIT_LIST_HEAD(&bundle->list);
324*266b0663SKrzysztof Zdziarski 		priv->bundle = bundle;
325*266b0663SKrzysztof Zdziarski 		priv->accel = accel;
326*266b0663SKrzysztof Zdziarski 
327*266b0663SKrzysztof Zdziarski 		mutex_init(&bundle->lock);
328*266b0663SKrzysztof Zdziarski 		mutex_init(&bundle->list_lock);
329*266b0663SKrzysztof Zdziarski 		if (!accel->bar)
330*266b0663SKrzysztof Zdziarski 			printf("ERROR: bar not defined in accel\n");
331*266b0663SKrzysztof Zdziarski 		else
332*266b0663SKrzysztof Zdziarski 			bundle->csr_addr = (void *)accel->bar->virt_addr;
333*266b0663SKrzysztof Zdziarski 	}
334*266b0663SKrzysztof Zdziarski }
335*266b0663SKrzysztof Zdziarski 
336*266b0663SKrzysztof Zdziarski /**
337*266b0663SKrzysztof Zdziarski  * Initialization bars on dev start.
338*266b0663SKrzysztof Zdziarski  */
339*266b0663SKrzysztof Zdziarski static inline void
adf_uio_init_bundle_dev(struct adf_uio_control_accel * accel,struct adf_accel_dev * accel_dev,unsigned int nb_bundles)340*266b0663SKrzysztof Zdziarski adf_uio_init_bundle_dev(struct adf_uio_control_accel *accel,
341*266b0663SKrzysztof Zdziarski 			struct adf_accel_dev *accel_dev,
342*266b0663SKrzysztof Zdziarski 			unsigned int nb_bundles)
343*266b0663SKrzysztof Zdziarski {
344*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_bundle *bundle;
345*266b0663SKrzysztof Zdziarski 	unsigned int i;
346*266b0663SKrzysztof Zdziarski 
347*266b0663SKrzysztof Zdziarski 	for (i = 0; i < nb_bundles; i++) {
348*266b0663SKrzysztof Zdziarski 		bundle = &accel->bundle[i];
349*266b0663SKrzysztof Zdziarski 		bundle->obj =
350*266b0663SKrzysztof Zdziarski 		    adf_uio_map_bar(accel_dev, bundle->hardware_bundle_number);
351*266b0663SKrzysztof Zdziarski 		if (!bundle->obj) {
352*266b0663SKrzysztof Zdziarski 			device_printf(GET_DEV(accel_dev),
353*266b0663SKrzysztof Zdziarski 				      "ERROR in adf_alloc_bundle %d\n",
354*266b0663SKrzysztof Zdziarski 				      __LINE__);
355*266b0663SKrzysztof Zdziarski 		}
356*266b0663SKrzysztof Zdziarski 	}
357*266b0663SKrzysztof Zdziarski }
358*266b0663SKrzysztof Zdziarski 
359*266b0663SKrzysztof Zdziarski int
adf_uio_register(struct adf_accel_dev * accel_dev)360*266b0663SKrzysztof Zdziarski adf_uio_register(struct adf_accel_dev *accel_dev)
361*266b0663SKrzysztof Zdziarski {
362*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = NULL;
363*266b0663SKrzysztof Zdziarski 	char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
364*266b0663SKrzysztof Zdziarski 	int nb_bundles;
365*266b0663SKrzysztof Zdziarski 
366*266b0663SKrzysztof Zdziarski 	if (!accel_dev) {
367*266b0663SKrzysztof Zdziarski 		printf("%s - accel_dev is NULL\n", __func__);
368*266b0663SKrzysztof Zdziarski 		return EFAULT;
369*266b0663SKrzysztof Zdziarski 	}
370*266b0663SKrzysztof Zdziarski 
371*266b0663SKrzysztof Zdziarski 	if (adf_cfg_get_param_value(
372*266b0663SKrzysztof Zdziarski 		accel_dev, ADF_GENERAL_SEC, ADF_FIRST_USER_BUNDLE, val)) {
373*266b0663SKrzysztof Zdziarski 		nb_bundles = 0;
374*266b0663SKrzysztof Zdziarski 	} else {
375*266b0663SKrzysztof Zdziarski 		nb_bundles = GET_MAX_BANKS(accel_dev);
376*266b0663SKrzysztof Zdziarski 	}
377*266b0663SKrzysztof Zdziarski 
378*266b0663SKrzysztof Zdziarski 	if (nb_bundles) {
379*266b0663SKrzysztof Zdziarski 		accel = malloc(sizeof(*accel) +
380*266b0663SKrzysztof Zdziarski 				   nb_bundles *
381*266b0663SKrzysztof Zdziarski 				       sizeof(struct adf_uio_control_bundle),
382*266b0663SKrzysztof Zdziarski 			       M_QAT,
383*266b0663SKrzysztof Zdziarski 			       M_WAITOK | M_ZERO);
384*266b0663SKrzysztof Zdziarski 		mtx_init(&accel->lock, "qat uio", NULL, MTX_DEF);
385*266b0663SKrzysztof Zdziarski 		accel->accel_dev = accel_dev;
386*266b0663SKrzysztof Zdziarski 		accel->bar = accel_dev->accel_pci_dev.pci_bars +
387*266b0663SKrzysztof Zdziarski 		    ADF_UIO_GET_BAR(accel_dev);
388*266b0663SKrzysztof Zdziarski 
389*266b0663SKrzysztof Zdziarski 		adf_uio_init_accel_ctrl(accel, accel_dev, nb_bundles);
390*266b0663SKrzysztof Zdziarski 		accel->cdev = make_dev(&adf_uio_cdevsw,
391*266b0663SKrzysztof Zdziarski 				       0,
392*266b0663SKrzysztof Zdziarski 				       UID_ROOT,
393*266b0663SKrzysztof Zdziarski 				       GID_WHEEL,
394*266b0663SKrzysztof Zdziarski 				       0600,
395*266b0663SKrzysztof Zdziarski 				       "%s",
396*266b0663SKrzysztof Zdziarski 				       device_get_nameunit(GET_DEV(accel_dev)));
397*266b0663SKrzysztof Zdziarski 		if (accel->cdev == NULL) {
398*266b0663SKrzysztof Zdziarski 			mtx_destroy(&accel->lock);
399*266b0663SKrzysztof Zdziarski 			goto fail_clean;
400*266b0663SKrzysztof Zdziarski 		}
401*266b0663SKrzysztof Zdziarski 		accel->cdev->si_drv1 = accel_dev;
402*266b0663SKrzysztof Zdziarski 		accel_dev->accel = accel;
403*266b0663SKrzysztof Zdziarski 		cv_init(&accel->cleanup_ok, "uio_accel_cv");
404*266b0663SKrzysztof Zdziarski 
405*266b0663SKrzysztof Zdziarski 		adf_uio_init_bundle_dev(accel, accel_dev, nb_bundles);
406*266b0663SKrzysztof Zdziarski 	}
407*266b0663SKrzysztof Zdziarski 	return 0;
408*266b0663SKrzysztof Zdziarski fail_clean:
409*266b0663SKrzysztof Zdziarski 	free(accel, M_QAT);
410*266b0663SKrzysztof Zdziarski 	device_printf(GET_DEV(accel_dev), "Failed to register UIO devices\n");
411*266b0663SKrzysztof Zdziarski 	return ENODEV;
412*266b0663SKrzysztof Zdziarski }
413*266b0663SKrzysztof Zdziarski 
414*266b0663SKrzysztof Zdziarski void
adf_uio_remove(struct adf_accel_dev * accel_dev)415*266b0663SKrzysztof Zdziarski adf_uio_remove(struct adf_accel_dev *accel_dev)
416*266b0663SKrzysztof Zdziarski {
417*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_accel *accel = accel_dev->accel;
418*266b0663SKrzysztof Zdziarski 	struct adf_uio_control_bundle *bundle;
419*266b0663SKrzysztof Zdziarski 	unsigned int i;
420*266b0663SKrzysztof Zdziarski 
421*266b0663SKrzysztof Zdziarski 	if (accel) {
422*266b0663SKrzysztof Zdziarski 		/* Un-mapping all bars */
423*266b0663SKrzysztof Zdziarski 		for (i = 0; i < accel->nb_bundles; i++) {
424*266b0663SKrzysztof Zdziarski 			bundle = &accel->bundle[i];
425*266b0663SKrzysztof Zdziarski 			vm_object_deallocate(bundle->obj);
426*266b0663SKrzysztof Zdziarski 		}
427*266b0663SKrzysztof Zdziarski 
428*266b0663SKrzysztof Zdziarski 		destroy_dev(accel->cdev);
429*266b0663SKrzysztof Zdziarski 		mtx_lock(&accel->lock);
430*266b0663SKrzysztof Zdziarski 		while (accel->num_handles) {
431*266b0663SKrzysztof Zdziarski 			cv_timedwait_sig(&accel->cleanup_ok,
432*266b0663SKrzysztof Zdziarski 					 &accel->lock,
433*266b0663SKrzysztof Zdziarski 					 3 * hz);
434*266b0663SKrzysztof Zdziarski 		}
435*266b0663SKrzysztof Zdziarski 		mtx_unlock(&accel->lock);
436*266b0663SKrzysztof Zdziarski 		mtx_destroy(&accel->lock);
437*266b0663SKrzysztof Zdziarski 		cv_destroy(&accel->cleanup_ok);
438*266b0663SKrzysztof Zdziarski 		free(accel, M_QAT);
439*266b0663SKrzysztof Zdziarski 		accel_dev->accel = NULL;
440*266b0663SKrzysztof Zdziarski 	}
441*266b0663SKrzysztof Zdziarski }
442