]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/infiniband/hw/hfi1/file_ops.c
IB/hfi1: Use filedata rather than filepointer
[karo-tx-linux.git] / drivers / infiniband / hw / hfi1 / file_ops.c
index f78c739b330a45cfcb99a7a14d9c3e6d2f72c549..ab798a81d6b4b8b04d9134252ed69082cd27c406 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015-2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
 /*
  * File operation functions
  */
-static int hfi1_file_open(struct inode *, struct file *);
-static int hfi1_file_close(struct inode *, struct file *);
-static ssize_t hfi1_write_iter(struct kiocb *, struct iov_iter *);
-static unsigned int hfi1_poll(struct file *, struct poll_table_struct *);
-static int hfi1_file_mmap(struct file *, struct vm_area_struct *);
-
-static u64 kvirt_to_phys(void *);
-static int assign_ctxt(struct file *, struct hfi1_user_info *);
-static int init_subctxts(struct hfi1_ctxtdata *, const struct hfi1_user_info *);
-static int user_init(struct file *);
-static int get_ctxt_info(struct file *, void __user *, __u32);
-static int get_base_info(struct file *, void __user *, __u32);
-static int setup_ctxt(struct file *);
-static int setup_subctxt(struct hfi1_ctxtdata *);
-static int get_user_context(struct file *, struct hfi1_user_info *, int);
-static int find_shared_ctxt(struct file *, const struct hfi1_user_info *);
-static int allocate_ctxt(struct file *, struct hfi1_devdata *,
-                        struct hfi1_user_info *);
-static unsigned int poll_urgent(struct file *, struct poll_table_struct *);
-static unsigned int poll_next(struct file *, struct poll_table_struct *);
-static int user_event_ack(struct hfi1_ctxtdata *, int, unsigned long);
-static int set_ctxt_pkey(struct hfi1_ctxtdata *, unsigned, u16);
-static int manage_rcvq(struct hfi1_ctxtdata *, unsigned, int);
-static int vma_fault(struct vm_fault *);
+static int hfi1_file_open(struct inode *inode, struct file *fp);
+static int hfi1_file_close(struct inode *inode, struct file *fp);
+static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from);
+static unsigned int hfi1_poll(struct file *fp, struct poll_table_struct *pt);
+static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma);
+
+static u64 kvirt_to_phys(void *addr);
+static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo);
+static int init_subctxts(struct hfi1_ctxtdata *uctxt,
+                        const struct hfi1_user_info *uinfo);
+static int user_init(struct hfi1_filedata *fd);
+static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len);
+static int get_base_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len);
+static int setup_ctxt(struct hfi1_filedata *fd);
+static int setup_subctxt(struct hfi1_ctxtdata *uctxt);
+static int get_user_context(struct hfi1_filedata *fd,
+                           struct hfi1_user_info *uinfo, int devno);
+static int find_shared_ctxt(struct hfi1_filedata *fd,
+                           const struct hfi1_user_info *uinfo);
+static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
+                        struct hfi1_user_info *uinfo);
+static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt);
+static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt);
+static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt,
+                         unsigned long events);
+static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned subctxt,
+                        u16 pkey);
+static int manage_rcvq(struct hfi1_ctxtdata *uctxt, unsigned subctxt,
+                      int start_stop);
+static int vma_fault(struct vm_fault *vmf);
 static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                            unsigned long arg);
 
@@ -232,17 +240,17 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                ret = assign_ctxt(fp, &uinfo);
                if (ret < 0)
                        return ret;
-               ret = setup_ctxt(fp);
+               ret = setup_ctxt(fd);
                if (ret)
                        return ret;
-               ret = user_init(fp);
+               ret = user_init(fd);
                break;
        case HFI1_IOCTL_CTXT_INFO:
-               ret = get_ctxt_info(fp, (void __user *)(unsigned long)arg,
+               ret = get_ctxt_info(fd, (void __user *)(unsigned long)arg,
                                    sizeof(struct hfi1_ctxt_info));
                break;
        case HFI1_IOCTL_USER_INFO:
-               ret = get_base_info(fp, (void __user *)(unsigned long)arg,
+               ret = get_base_info(fd, (void __user *)(unsigned long)arg,
                                    sizeof(struct hfi1_base_info));
                break;
        case HFI1_IOCTL_CREDIT_UPD:
@@ -256,7 +264,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_setup(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_setup(fd, &tinfo);
                if (!ret) {
                        /*
                         * Copy the number of tidlist entries we used
@@ -278,7 +286,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_clear(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_clear(fd, &tinfo);
                if (ret)
                        break;
                addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
@@ -293,7 +301,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_invalid(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_invalid(fd, &tinfo);
                if (ret)
                        break;
                addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
@@ -430,7 +438,7 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
                unsigned long count = 0;
 
                ret = hfi1_user_sdma_process_request(
-                       kiocb->ki_filp, (struct iovec *)(from->iov + done),
+                       fd, (struct iovec *)(from->iov + done),
                        dim, &count);
                if (ret) {
                        reqs = ret;
@@ -586,8 +594,8 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                 * knows where it's own bitmap is within the page.
                 */
                memaddr = (unsigned long)(dd->events +
-                                         ((uctxt->ctxt - dd->first_user_ctxt) *
-                                          HFI1_MAX_SHARED_CTXTS)) & PAGE_MASK;
+                                 ((uctxt->ctxt - dd->first_dyn_alloc_ctxt) *
+                                  HFI1_MAX_SHARED_CTXTS)) & PAGE_MASK;
                memlen = PAGE_SIZE;
                /*
                 * v3.7 removes VM_RESERVED but the effect is kept by
@@ -597,6 +605,10 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                vmf = 1;
                break;
        case STATUS:
+               if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+                       ret = -EPERM;
+                       goto done;
+               }
                memaddr = kvirt_to_phys((void *)dd->status);
                memlen = PAGE_SIZE;
                flags |= VM_IO | VM_DONTEXPAND;
@@ -752,11 +764,14 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
        /* release the cpu */
        hfi1_put_proc_affinity(fdata->rec_cpu_num);
 
+       /* clean up rcv side */
+       hfi1_user_exp_rcv_free(fdata);
+
        /*
         * Clear any left over, unhandled events so the next process that
         * gets this context doesn't get confused.
         */
-       ev = dd->events + ((uctxt->ctxt - dd->first_user_ctxt) *
+       ev = dd->events + ((uctxt->ctxt - dd->first_dyn_alloc_ctxt) *
                           HFI1_MAX_SHARED_CTXTS) + fdata->subctxt;
        *ev = 0;
 
@@ -791,7 +806,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
 
        dd->rcd[uctxt->ctxt] = NULL;
 
-       hfi1_user_exp_rcv_free(fdata);
+       hfi1_user_exp_rcv_grp_free(uctxt);
        hfi1_clear_ctxt_pkey(dd, uctxt->ctxt);
 
        uctxt->rcvwait_to = 0;
@@ -850,7 +865,7 @@ static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo)
        if (uinfo->subctxt_cnt) {
                struct hfi1_filedata *fd = fp->private_data;
 
-               ret = find_shared_ctxt(fp, uinfo);
+               ret = find_shared_ctxt(fd, uinfo);
                if (ret < 0)
                        goto done_unlock;
                if (ret) {
@@ -865,7 +880,7 @@ static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo)
         */
        if (!ret) {
                i_minor = iminor(file_inode(fp)) - HFI1_USER_MINOR_BASE;
-               ret = get_user_context(fp, uinfo, i_minor);
+               ret = get_user_context(fp->private_data, uinfo, i_minor);
        }
 done_unlock:
        mutex_unlock(&hfi1_mutex);
@@ -873,8 +888,8 @@ done:
        return ret;
 }
 
-static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
-                           int devno)
+static int get_user_context(struct hfi1_filedata *fd,
+                           struct hfi1_user_info *uinfo, int devno)
 {
        struct hfi1_devdata *dd = NULL;
        int devmax, npresent, nup;
@@ -892,15 +907,14 @@ static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
        else if (!dd->freectxts)
                return -EBUSY;
 
-       return allocate_ctxt(fp, dd, uinfo);
+       return allocate_ctxt(fd, dd, uinfo);
 }
 
-static int find_shared_ctxt(struct file *fp,
+static int find_shared_ctxt(struct hfi1_filedata *fd,
                            const struct hfi1_user_info *uinfo)
 {
        int devmax, ndev, i;
        int ret = 0;
-       struct hfi1_filedata *fd = fp->private_data;
 
        devmax = hfi1_count_units(NULL, NULL);
 
@@ -909,12 +923,18 @@ static int find_shared_ctxt(struct file *fp,
 
                if (!(dd && (dd->flags & HFI1_PRESENT) && dd->kregbase))
                        continue;
-               for (i = dd->first_user_ctxt; i < dd->num_rcv_contexts; i++) {
+               for (i = dd->first_dyn_alloc_ctxt;
+                    i < dd->num_rcv_contexts; i++) {
                        struct hfi1_ctxtdata *uctxt = dd->rcd[i];
 
                        /* Skip ctxts which are not yet open */
                        if (!uctxt || !uctxt->cnt)
                                continue;
+
+                       /* Skip dynamically allocted kernel contexts */
+                       if (uctxt->sc && (uctxt->sc->type == SC_KERNEL))
+                               continue;
+
                        /* Skip ctxt if it doesn't match the requested one */
                        if (memcmp(uctxt->uuid, uinfo->uuid,
                                   sizeof(uctxt->uuid)) ||
@@ -941,10 +961,9 @@ done:
        return ret;
 }
 
-static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
+static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
                         struct hfi1_user_info *uinfo)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt;
        unsigned ctxt;
        int ret, numa;
@@ -960,7 +979,8 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
                return -EIO;
        }
 
-       for (ctxt = dd->first_user_ctxt; ctxt < dd->num_rcv_contexts; ctxt++)
+       for (ctxt = dd->first_dyn_alloc_ctxt;
+            ctxt < dd->num_rcv_contexts; ctxt++)
                if (!dd->rcd[ctxt])
                        break;
 
@@ -1093,10 +1113,9 @@ bail:
        return ret;
 }
 
-static int user_init(struct file *fp)
+static int user_init(struct hfi1_filedata *fd)
 {
        unsigned int rcvctrl_ops = 0;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
 
        /* make sure that the context has already been setup */
@@ -1159,10 +1178,10 @@ static int user_init(struct file *fp)
        return 0;
 }
 
-static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
+static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len)
 {
        struct hfi1_ctxt_info cinfo;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        int ret = 0;
 
@@ -1200,9 +1219,8 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
        return ret;
 }
 
-static int setup_ctxt(struct file *fp)
+static int setup_ctxt(struct hfi1_filedata *fd)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        int ret = 0;
@@ -1237,7 +1255,7 @@ static int setup_ctxt(struct file *fp)
                        goto done;
        }
 
-       ret = hfi1_user_sdma_alloc_queues(uctxt, fp);
+       ret = hfi1_user_sdma_alloc_queues(uctxt, fd);
        if (ret)
                goto done;
        /*
@@ -1249,7 +1267,7 @@ static int setup_ctxt(struct file *fp)
         * (due to the above wait_event_interruptible() until the master
         * is setup.
         */
-       ret = hfi1_user_exp_rcv_init(fp);
+       ret = hfi1_user_exp_rcv_init(fd);
        if (ret)
                goto done;
 
@@ -1258,10 +1276,10 @@ done:
        return ret;
 }
 
-static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
+static int get_base_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len)
 {
        struct hfi1_base_info binfo;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        ssize_t sz;
@@ -1306,7 +1324,7 @@ static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
         */
        binfo.user_regbase = HFI1_MMAP_TOKEN(UREGS, uctxt->ctxt,
                                            fd->subctxt, 0);
-       offset = offset_in_page((((uctxt->ctxt - dd->first_user_ctxt) *
+       offset = offset_in_page((((uctxt->ctxt - dd->first_dyn_alloc_ctxt) *
                    HFI1_MAX_SHARED_CTXTS) + fd->subctxt) *
                  sizeof(*dd->events));
        binfo.events_bufbase = HFI1_MMAP_TOKEN(EVENTS, uctxt->ctxt,
@@ -1400,12 +1418,12 @@ int hfi1_set_uevent_bits(struct hfi1_pportdata *ppd, const int evtbit)
        }
 
        spin_lock_irqsave(&dd->uctxt_lock, flags);
-       for (ctxt = dd->first_user_ctxt; ctxt < dd->num_rcv_contexts;
+       for (ctxt = dd->first_dyn_alloc_ctxt; ctxt < dd->num_rcv_contexts;
             ctxt++) {
                uctxt = dd->rcd[ctxt];
                if (uctxt) {
                        unsigned long *evs = dd->events +
-                               (uctxt->ctxt - dd->first_user_ctxt) *
+                               (uctxt->ctxt - dd->first_dyn_alloc_ctxt) *
                                HFI1_MAX_SHARED_CTXTS;
                        int i;
                        /*
@@ -1477,7 +1495,7 @@ static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt,
        if (!dd->events)
                return 0;
 
-       evs = dd->events + ((uctxt->ctxt - dd->first_user_ctxt) *
+       evs = dd->events + ((uctxt->ctxt - dd->first_dyn_alloc_ctxt) *
                            HFI1_MAX_SHARED_CTXTS) + subctxt;
 
        for (i = 0; i <= _HFI1_MAX_EVENT_BIT; i++) {