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 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 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 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 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 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 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 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 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 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 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