Linux 4.2.1
[linux/fpc-iii.git] / drivers / misc / mic / host / mic_fops.c
blob85776d7327f372bfb14567b87f36e6b34891ff42
1 /*
2 * Intel MIC Platform Software Stack (MPSS)
4 * Copyright(c) 2013 Intel Corporation.
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.
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.
15 * The full GNU General Public License is included in this distribution in
16 * the file called "COPYING".
18 * Intel MIC Host driver.
21 #include <linux/poll.h>
22 #include <linux/pci.h>
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"
30 int mic_open(struct inode *inode, struct file *f)
32 struct mic_vdev *mvdev;
33 struct mic_device *mdev = container_of(inode->i_cdev,
34 struct mic_device, cdev);
36 mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
37 if (!mvdev)
38 return -ENOMEM;
40 init_waitqueue_head(&mvdev->waitq);
41 INIT_LIST_HEAD(&mvdev->list);
42 mvdev->mdev = mdev;
43 mvdev->virtio_id = -1;
45 f->private_data = mvdev;
46 return 0;
49 int mic_release(struct inode *inode, struct file *f)
51 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
53 if (-1 != mvdev->virtio_id)
54 mic_virtio_del_device(mvdev);
55 f->private_data = NULL;
56 kfree(mvdev);
57 return 0;
60 long mic_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
62 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
63 void __user *argp = (void __user *)arg;
64 int ret;
66 switch (cmd) {
67 case MIC_VIRTIO_ADD_DEVICE:
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;
76 break;
78 case MIC_VIRTIO_COPY_DESC:
80 struct mic_copy_desc copy;
82 ret = mic_vdev_inited(mvdev);
83 if (ret)
84 return ret;
86 if (copy_from_user(&copy, argp, sizeof(copy)))
87 return -EFAULT;
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);
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;
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;
108 break;
110 case MIC_VIRTIO_CONFIG_CHANGE:
112 ret = mic_vdev_inited(mvdev);
113 if (ret)
114 return ret;
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;
123 break;
125 default:
126 return -ENOIOCTLCMD;
128 return 0;
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.
137 unsigned int mic_poll(struct file *f, poll_table *wait)
139 struct mic_vdev *mvdev = (struct mic_vdev *)f->private_data;
140 int mask = 0;
142 poll_wait(f, &mvdev->waitq, wait);
144 if (mic_vdev_inited(mvdev)) {
145 mask = POLLERR;
146 } else if (mvdev->poll_wake) {
147 mvdev->poll_wake = 0;
148 mask = POLLIN | POLLOUT;
151 return mask;
154 static inline int
155 mic_query_offset(struct mic_vdev *mvdev, unsigned long offset,
156 unsigned long *size, unsigned long *pa)
158 struct mic_device *mdev = mvdev->mdev;
159 unsigned long start = MIC_DP_SIZE;
160 int i;
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 * ....
170 if (!offset) {
171 *pa = virt_to_phys(mdev->dp);
172 *size = MIC_DP_SIZE;
173 return 0;
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;
183 start += mvr->vring.len;
185 return -1;
189 * Maps the device page and virtio rings to user space for readonly access.
192 mic_mmap(struct file *f, struct vm_area_struct *vma)
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;
199 err = mic_vdev_inited(mvdev);
200 if (err)
201 return err;
203 if (vma->vm_flags & VM_WRITE)
204 return -EACCES;
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;
221 return 0;