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
30int mic_open(struct inode *inode, struct file *f)
31{
32	struct mic_vdev *mvdev;
33	struct mic_device *mdev = container_of(f->private_data,
34		struct mic_device, miscdev);
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
49int 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
60long 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 */
137unsigned 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
154static inline int
155mic_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 */
191int
192mic_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}
223