Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / misc / mic / host / mic_fops.c
1 /*
2  * Intel MIC Platform Software Stack (MPSS)
3  *
4  * Copyright(c) 2013 Intel Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License, version 2, as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * General Public License for more details.
14  *
15  * The full GNU General Public License is included in this distribution in
16  * the file called "COPYING".
17  *
18  * Intel MIC Host driver.
19  *
20  */
21 #include <linux/poll.h>
22 #include <linux/pci.h>
23
24 #include <linux/mic_common.h>
25 #include "../common/mic_dev.h"
26 #include "mic_device.h"
27 #include "mic_fops.h"
28 #include "mic_virtio.h"
29
30 int mic_open(struct inode *inode, struct file *f)
31 {
32         struct mic_vdev *mvdev;
33         struct mic_device *mdev = container_of(inode->i_cdev,
34                 struct mic_device, cdev);
35
36         mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
37         if (!mvdev)
38                 return -ENOMEM;
39
40         init_waitqueue_head(&mvdev->waitq);
41         INIT_LIST_HEAD(&mvdev->list);
42         mvdev->mdev = mdev;
43         mvdev->virtio_id = -1;
44
45         f->private_data = mvdev;
46         return 0;
47 }
48
49 int mic_release(struct inode *inode, struct file *f)
50 {
51         struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
52
53         if (-1 != mvdev->virtio_id)
54                 mic_virtio_del_device(mvdev);
55         f->private_data = NULL;
56         kfree(mvdev);
57         return 0;
58 }
59
60 long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
61 {
62         struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
63         void __user *argp = (void __user *)arg;
64         int ret;
65
66         switch (cmd) {
67         case MIC_VIRTIO_ADD_DEVICE:
68         {
69                 ret = mic_virtio_add_device(mvdev, argp);
70                 if (ret < 0) {
71                         dev_err(mic_dev(mvdev),
72                                 "%s %d errno ret %d\n",
73                                 __func__, __LINE__, ret);
74                         return ret;
75                 }
76                 break;
77         }
78         case MIC_VIRTIO_COPY_DESC:
79         {
80                 struct mic_copy_desc copy;
81
82                 ret = mic_vdev_inited(mvdev);
83                 if (ret)
84                         return ret;
85
86                 if (copy_from_user(&copy, argp, sizeof(copy)))
87                         return -EFAULT;
88
89                 dev_dbg(mic_dev(mvdev),
90                         "%s %d === iovcnt 0x%x vr_idx 0x%x update_used %d\n",
91                         __func__, __LINE__, copy.iovcnt, copy.vr_idx,
92                         copy.update_used);
93
94                 ret = mic_virtio_copy_desc(mvdev, &copy);
95                 if (ret < 0) {
96                         dev_err(mic_dev(mvdev),
97                                 "%s %d errno ret %d\n",
98                                 __func__, __LINE__, ret);
99                         return ret;
100                 }
101                 if (copy_to_user(
102                         &((struct mic_copy_desc __user *)argp)->out_len,
103                         &copy.out_len, sizeof(copy.out_len))) {
104                         dev_err(mic_dev(mvdev), "%s %d errno ret %d\n",
105                                 __func__, __LINE__, -EFAULT);
106                         return -EFAULT;
107                 }
108                 break;
109         }
110         case MIC_VIRTIO_CONFIG_CHANGE:
111         {
112                 ret = mic_vdev_inited(mvdev);
113                 if (ret)
114                         return ret;
115
116                 ret = mic_virtio_config_change(mvdev, argp);
117                 if (ret < 0) {
118                         dev_err(mic_dev(mvdev),
119                                 "%s %d errno ret %d\n",
120                                 __func__, __LINE__, ret);
121                         return ret;
122                 }
123                 break;
124         }
125         default:
126                 return -ENOIOCTLCMD;
127         };
128         return 0;
129 }
130
131 /*
132  * We return POLLIN | POLLOUT from poll when new buffers are enqueued, and
133  * not when previously enqueued buffers may be available. This means that
134  * in the card->host (TX) path, when userspace is unblocked by poll it
135  * must drain all available descriptors or it can stall.
136  */
137 unsigned int mic_poll(struct file *f, poll_table *wait)
138 {
139         struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
140         int mask = 0;
141
142         poll_wait(f, &mvdev->waitq, wait);
143
144         if (mic_vdev_inited(mvdev)) {
145                 mask = POLLERR;
146         } else if (mvdev->poll_wake) {
147                 mvdev->poll_wake = 0;
148                 mask = POLLIN | POLLOUT;
149         }
150
151         return mask;
152 }
153
154 static inline int
155 mic_query_offset(struct mic_vdev *mvdev, unsigned long offset,
156                  unsigned long *size, unsigned long *pa)
157 {
158         struct mic_device *mdev = mvdev->mdev;
159         unsigned long start = MIC_DP_SIZE;
160         int i;
161
162         /*
163          * MMAP interface is as follows:
164          * offset                               region
165          * 0x0                                  virtio device_page
166          * 0x1000                               first vring
167          * 0x1000 + size of 1st vring           second vring
168          * ....
169          */
170         if (!offset) {
171                 *pa = virt_to_phys(mdev->dp);
172                 *size = MIC_DP_SIZE;
173                 return 0;
174         }
175
176         for (i = 0; i < mvdev->dd->num_vq; i++) {
177                 struct mic_vringh *mvr = &mvdev->mvr[i];
178                 if (offset == start) {
179                         *pa = virt_to_phys(mvr->vring.va);
180                         *size = mvr->vring.len;
181                         return 0;
182                 }
183                 start += mvr->vring.len;
184         }
185         return -1;
186 }
187
188 /*
189  * Maps the device page and virtio rings to user space for readonly access.
190  */
191 int
192 mic_mmap(struct file *f, struct vm_area_struct *vma)
193 {
194         struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
195         unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
196         unsigned long pa, size = vma->vm_end - vma->vm_start, size_rem = size;
197         int i, err;
198
199         err = mic_vdev_inited(mvdev);
200         if (err)
201                 return err;
202
203         if (vma->vm_flags & VM_WRITE)
204                 return -EACCES;
205
206         while (size_rem) {
207                 i = mic_query_offset(mvdev, offset, &size, &pa);
208                 if (i < 0)
209                         return -EINVAL;
210                 err = remap_pfn_range(vma, vma->vm_start + offset,
211                         pa >> PAGE_SHIFT, size, vma->vm_page_prot);
212                 if (err)
213                         return err;
214                 dev_dbg(mic_dev(mvdev),
215                         "%s %d type %d size 0x%lx off 0x%lx pa 0x%lx vma 0x%lx\n",
216                         __func__, __LINE__, mvdev->virtio_id, size, offset,
217                         pa, vma->vm_start + offset);
218                 size_rem -= size;
219                 offset += size;
220         }
221         return 0;
222 }