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