aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mic
diff options
context:
space:
mode:
authorSudeep Dutt <sudeep.dutt@intel.com>2016-02-08 18:48:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-02-09 20:32:37 -0500
commitef39830c35838696013a2f6c16f6728c4a9dcefd (patch)
treebd8a092e201d63149755d54bbbe3bfa7cf32597e /drivers/misc/mic
parent4ddbdbb90d2ec7d7db93c98936faf3dad75f479b (diff)
misc: mic: Remove MIC X100 host virtio functionality
This patch deletes the virtio functionality from the MIC X100 host driver. A subsequent patch will re-enable this functionality by consolidating the hardware independent logic in a new Virtio over PCIe (VOP) driver. Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mic')
-rw-r--r--drivers/misc/mic/host/Makefile2
-rw-r--r--drivers/misc/mic/host/mic_boot.c2
-rw-r--r--drivers/misc/mic/host/mic_debugfs.c190
-rw-r--r--drivers/misc/mic/host/mic_device.h6
-rw-r--r--drivers/misc/mic/host/mic_fops.c222
-rw-r--r--drivers/misc/mic/host/mic_fops.h32
-rw-r--r--drivers/misc/mic/host/mic_main.c48
-rw-r--r--drivers/misc/mic/host/mic_virtio.c811
-rw-r--r--drivers/misc/mic/host/mic_virtio.h155
9 files changed, 4 insertions, 1464 deletions
diff --git a/drivers/misc/mic/host/Makefile b/drivers/misc/mic/host/Makefile
index 004d3db0f990..f3b502333ded 100644
--- a/drivers/misc/mic/host/Makefile
+++ b/drivers/misc/mic/host/Makefile
@@ -9,5 +9,3 @@ mic_host-objs += mic_smpt.o
9mic_host-objs += mic_intr.o 9mic_host-objs += mic_intr.o
10mic_host-objs += mic_boot.o 10mic_host-objs += mic_boot.o
11mic_host-objs += mic_debugfs.o 11mic_host-objs += mic_debugfs.o
12mic_host-objs += mic_fops.o
13mic_host-objs += mic_virtio.o
diff --git a/drivers/misc/mic/host/mic_boot.c b/drivers/misc/mic/host/mic_boot.c
index 7845564dff64..3df305f6282c 100644
--- a/drivers/misc/mic/host/mic_boot.c
+++ b/drivers/misc/mic/host/mic_boot.c
@@ -28,7 +28,6 @@
28#include "../common/mic_dev.h" 28#include "../common/mic_dev.h"
29#include "mic_device.h" 29#include "mic_device.h"
30#include "mic_smpt.h" 30#include "mic_smpt.h"
31#include "mic_virtio.h"
32 31
33static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev) 32static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
34{ 33{
@@ -423,7 +422,6 @@ static void _mic_stop(struct cosm_device *cdev, bool force)
423 * will be the first to be registered and the last to be 422 * will be the first to be registered and the last to be
424 * unregistered. 423 * unregistered.
425 */ 424 */
426 mic_virtio_reset_devices(mdev);
427 scif_unregister_device(mdev->scdev); 425 scif_unregister_device(mdev->scdev);
428 mic_free_dma_chans(mdev); 426 mic_free_dma_chans(mdev);
429 mbus_unregister_device(mdev->dma_mbdev); 427 mbus_unregister_device(mdev->dma_mbdev);
diff --git a/drivers/misc/mic/host/mic_debugfs.c b/drivers/misc/mic/host/mic_debugfs.c
index 10581600777a..0a9daba8bb5d 100644
--- a/drivers/misc/mic/host/mic_debugfs.c
+++ b/drivers/misc/mic/host/mic_debugfs.c
@@ -26,7 +26,6 @@
26#include "../common/mic_dev.h" 26#include "../common/mic_dev.h"
27#include "mic_device.h" 27#include "mic_device.h"
28#include "mic_smpt.h" 28#include "mic_smpt.h"
29#include "mic_virtio.h"
30 29
31/* Debugfs parent dir */ 30/* Debugfs parent dir */
32static struct dentry *mic_dbg; 31static struct dentry *mic_dbg;
@@ -100,190 +99,6 @@ static const struct file_operations post_code_ops = {
100 .release = mic_post_code_debug_release 99 .release = mic_post_code_debug_release
101}; 100};
102 101
103static int mic_dp_show(struct seq_file *s, void *pos)
104{
105 struct mic_device *mdev = s->private;
106 struct mic_device_desc *d;
107 struct mic_device_ctrl *dc;
108 struct mic_vqconfig *vqconfig;
109 __u32 *features;
110 __u8 *config;
111 struct mic_bootparam *bootparam = mdev->dp;
112 int i, j;
113
114 seq_printf(s, "Bootparam: magic 0x%x\n",
115 bootparam->magic);
116 seq_printf(s, "Bootparam: h2c_config_db %d\n",
117 bootparam->h2c_config_db);
118 seq_printf(s, "Bootparam: node_id %d\n",
119 bootparam->node_id);
120 seq_printf(s, "Bootparam: c2h_scif_db %d\n",
121 bootparam->c2h_scif_db);
122 seq_printf(s, "Bootparam: h2c_scif_db %d\n",
123 bootparam->h2c_scif_db);
124 seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
125 bootparam->scif_host_dma_addr);
126 seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
127 bootparam->scif_card_dma_addr);
128
129
130 for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
131 i += mic_total_desc_size(d)) {
132 d = mdev->dp + i;
133 dc = (void *)d + mic_aligned_desc_size(d);
134
135 /* end of list */
136 if (d->type == 0)
137 break;
138
139 if (d->type == -1)
140 continue;
141
142 seq_printf(s, "Type %d ", d->type);
143 seq_printf(s, "Num VQ %d ", d->num_vq);
144 seq_printf(s, "Feature Len %d\n", d->feature_len);
145 seq_printf(s, "Config Len %d ", d->config_len);
146 seq_printf(s, "Shutdown Status %d\n", d->status);
147
148 for (j = 0; j < d->num_vq; j++) {
149 vqconfig = mic_vq_config(d) + j;
150 seq_printf(s, "vqconfig[%d]: ", j);
151 seq_printf(s, "address 0x%llx ", vqconfig->address);
152 seq_printf(s, "num %d ", vqconfig->num);
153 seq_printf(s, "used address 0x%llx\n",
154 vqconfig->used_address);
155 }
156
157 features = (__u32 *)mic_vq_features(d);
158 seq_printf(s, "Features: Host 0x%x ", features[0]);
159 seq_printf(s, "Guest 0x%x\n", features[1]);
160
161 config = mic_vq_configspace(d);
162 for (j = 0; j < d->config_len; j++)
163 seq_printf(s, "config[%d]=%d\n", j, config[j]);
164
165 seq_puts(s, "Device control:\n");
166 seq_printf(s, "Config Change %d ", dc->config_change);
167 seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
168 seq_printf(s, "Guest Ack %d ", dc->guest_ack);
169 seq_printf(s, "Host ack %d\n", dc->host_ack);
170 seq_printf(s, "Used address updated %d ",
171 dc->used_address_updated);
172 seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
173 seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
174 seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
175 }
176
177 return 0;
178}
179
180static int mic_dp_debug_open(struct inode *inode, struct file *file)
181{
182 return single_open(file, mic_dp_show, inode->i_private);
183}
184
185static int mic_dp_debug_release(struct inode *inode, struct file *file)
186{
187 return single_release(inode, file);
188}
189
190static const struct file_operations dp_ops = {
191 .owner = THIS_MODULE,
192 .open = mic_dp_debug_open,
193 .read = seq_read,
194 .llseek = seq_lseek,
195 .release = mic_dp_debug_release
196};
197
198static int mic_vdev_info_show(struct seq_file *s, void *unused)
199{
200 struct mic_device *mdev = s->private;
201 struct list_head *pos, *tmp;
202 struct mic_vdev *mvdev;
203 int i, j;
204
205 mutex_lock(&mdev->mic_mutex);
206 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
207 mvdev = list_entry(pos, struct mic_vdev, list);
208 seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
209 mvdev->virtio_id,
210 mic_vdevup(mvdev) ? "UP" : "DOWN",
211 mvdev->in_bytes,
212 mvdev->out_bytes);
213 for (i = 0; i < MIC_MAX_VRINGS; i++) {
214 struct vring_desc *desc;
215 struct vring_avail *avail;
216 struct vring_used *used;
217 struct mic_vringh *mvr = &mvdev->mvr[i];
218 struct vringh *vrh = &mvr->vrh;
219 int num = vrh->vring.num;
220 if (!num)
221 continue;
222 desc = vrh->vring.desc;
223 seq_printf(s, "vring i %d avail_idx %d",
224 i, mvr->vring.info->avail_idx & (num - 1));
225 seq_printf(s, " vring i %d avail_idx %d\n",
226 i, mvr->vring.info->avail_idx);
227 seq_printf(s, "vrh i %d weak_barriers %d",
228 i, vrh->weak_barriers);
229 seq_printf(s, " last_avail_idx %d last_used_idx %d",
230 vrh->last_avail_idx, vrh->last_used_idx);
231 seq_printf(s, " completed %d\n", vrh->completed);
232 for (j = 0; j < num; j++) {
233 seq_printf(s, "desc[%d] addr 0x%llx len %d",
234 j, desc->addr, desc->len);
235 seq_printf(s, " flags 0x%x next %d\n",
236 desc->flags, desc->next);
237 desc++;
238 }
239 avail = vrh->vring.avail;
240 seq_printf(s, "avail flags 0x%x idx %d\n",
241 vringh16_to_cpu(vrh, avail->flags),
242 vringh16_to_cpu(vrh, avail->idx) & (num - 1));
243 seq_printf(s, "avail flags 0x%x idx %d\n",
244 vringh16_to_cpu(vrh, avail->flags),
245 vringh16_to_cpu(vrh, avail->idx));
246 for (j = 0; j < num; j++)
247 seq_printf(s, "avail ring[%d] %d\n",
248 j, avail->ring[j]);
249 used = vrh->vring.used;
250 seq_printf(s, "used flags 0x%x idx %d\n",
251 vringh16_to_cpu(vrh, used->flags),
252 vringh16_to_cpu(vrh, used->idx) & (num - 1));
253 seq_printf(s, "used flags 0x%x idx %d\n",
254 vringh16_to_cpu(vrh, used->flags),
255 vringh16_to_cpu(vrh, used->idx));
256 for (j = 0; j < num; j++)
257 seq_printf(s, "used ring[%d] id %d len %d\n",
258 j, vringh32_to_cpu(vrh,
259 used->ring[j].id),
260 vringh32_to_cpu(vrh,
261 used->ring[j].len));
262 }
263 }
264 mutex_unlock(&mdev->mic_mutex);
265
266 return 0;
267}
268
269static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
270{
271 return single_open(file, mic_vdev_info_show, inode->i_private);
272}
273
274static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
275{
276 return single_release(inode, file);
277}
278
279static const struct file_operations vdev_info_ops = {
280 .owner = THIS_MODULE,
281 .open = mic_vdev_info_debug_open,
282 .read = seq_read,
283 .llseek = seq_lseek,
284 .release = mic_vdev_info_debug_release
285};
286
287static int mic_msi_irq_info_show(struct seq_file *s, void *pos) 102static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
288{ 103{
289 struct mic_device *mdev = s->private; 104 struct mic_device *mdev = s->private;
@@ -367,11 +182,6 @@ void mic_create_debug_dir(struct mic_device *mdev)
367 debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev, 182 debugfs_create_file("post_code", 0444, mdev->dbg_dir, mdev,
368 &post_code_ops); 183 &post_code_ops);
369 184
370 debugfs_create_file("dp", 0444, mdev->dbg_dir, mdev, &dp_ops);
371
372 debugfs_create_file("vdev_info", 0444, mdev->dbg_dir, mdev,
373 &vdev_info_ops);
374
375 debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev, 185 debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir, mdev,
376 &msi_irq_info_ops); 186 &msi_irq_info_ops);
377} 187}
diff --git a/drivers/misc/mic/host/mic_device.h b/drivers/misc/mic/host/mic_device.h
index 461184a12fbb..8460de122929 100644
--- a/drivers/misc/mic/host/mic_device.h
+++ b/drivers/misc/mic/host/mic_device.h
@@ -64,9 +64,6 @@ extern struct cosm_hw_ops cosm_hw_ops;
64 * @bootaddr: MIC boot address. 64 * @bootaddr: MIC boot address.
65 * @dp: virtio device page 65 * @dp: virtio device page
66 * @dp_dma_addr: virtio device page DMA address. 66 * @dp_dma_addr: virtio device page DMA address.
67 * @name: name for the misc char device
68 * @miscdev: registered misc char device
69 * @vdev_list: list of virtio devices.
70 * @dma_mbdev: MIC BUS DMA device. 67 * @dma_mbdev: MIC BUS DMA device.
71 * @dma_ch - Array of DMA channels 68 * @dma_ch - Array of DMA channels
72 * @num_dma_ch - Number of DMA channels available 69 * @num_dma_ch - Number of DMA channels available
@@ -91,9 +88,6 @@ struct mic_device {
91 u32 bootaddr; 88 u32 bootaddr;
92 void *dp; 89 void *dp;
93 dma_addr_t dp_dma_addr; 90 dma_addr_t dp_dma_addr;
94 char name[16];
95 struct miscdevice miscdev;
96 struct list_head vdev_list;
97 struct mbus_device *dma_mbdev; 91 struct mbus_device *dma_mbdev;
98 struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN]; 92 struct dma_chan *dma_ch[MIC_MAX_DMA_CHAN];
99 int num_dma_ch; 93 int num_dma_ch;
diff --git a/drivers/misc/mic/host/mic_fops.c b/drivers/misc/mic/host/mic_fops.c
deleted file mode 100644
index 8cc1d90cd949..000000000000
--- a/drivers/misc/mic/host/mic_fops.c
+++ /dev/null
@@ -1,222 +0,0 @@
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}
diff --git a/drivers/misc/mic/host/mic_fops.h b/drivers/misc/mic/host/mic_fops.h
deleted file mode 100644
index dc3893dff667..000000000000
--- a/drivers/misc/mic/host/mic_fops.h
+++ /dev/null
@@ -1,32 +0,0 @@
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#ifndef _MIC_FOPS_H_
22#define _MIC_FOPS_H_
23
24int mic_open(struct inode *inode, struct file *filp);
25int mic_release(struct inode *inode, struct file *filp);
26ssize_t mic_read(struct file *filp, char __user *buf,
27 size_t count, loff_t *pos);
28long mic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
29int mic_mmap(struct file *f, struct vm_area_struct *vma);
30unsigned int mic_poll(struct file *f, poll_table *wait);
31
32#endif
diff --git a/drivers/misc/mic/host/mic_main.c b/drivers/misc/mic/host/mic_main.c
index 153894e7ed5b..400def2106e7 100644
--- a/drivers/misc/mic/host/mic_main.c
+++ b/drivers/misc/mic/host/mic_main.c
@@ -27,8 +27,6 @@
27#include "mic_device.h" 27#include "mic_device.h"
28#include "mic_x100.h" 28#include "mic_x100.h"
29#include "mic_smpt.h" 29#include "mic_smpt.h"
30#include "mic_fops.h"
31#include "mic_virtio.h"
32 30
33static const char mic_driver_name[] = "mic"; 31static const char mic_driver_name[] = "mic";
34 32
@@ -57,17 +55,6 @@ MODULE_DEVICE_TABLE(pci, mic_pci_tbl);
57 55
58/* ID allocator for MIC devices */ 56/* ID allocator for MIC devices */
59static struct ida g_mic_ida; 57static struct ida g_mic_ida;
60/* Base device node number for MIC devices */
61static dev_t g_mic_devno;
62
63static const struct file_operations mic_fops = {
64 .open = mic_open,
65 .release = mic_release,
66 .unlocked_ioctl = mic_ioctl,
67 .poll = mic_poll,
68 .mmap = mic_mmap,
69 .owner = THIS_MODULE,
70};
71 58
72/* Initialize the device page */ 59/* Initialize the device page */
73static int mic_dp_init(struct mic_device *mdev) 60static int mic_dp_init(struct mic_device *mdev)
@@ -169,7 +156,6 @@ mic_device_init(struct mic_device *mdev, struct pci_dev *pdev)
169 mic_ops_init(mdev); 156 mic_ops_init(mdev);
170 mutex_init(&mdev->mic_mutex); 157 mutex_init(&mdev->mic_mutex);
171 mdev->irq_info.next_avail_src = 0; 158 mdev->irq_info.next_avail_src = 0;
172 INIT_LIST_HEAD(&mdev->vdev_list);
173} 159}
174 160
175/** 161/**
@@ -259,30 +245,15 @@ static int mic_probe(struct pci_dev *pdev,
259 goto smpt_uninit; 245 goto smpt_uninit;
260 } 246 }
261 mic_bootparam_init(mdev); 247 mic_bootparam_init(mdev);
262
263 mic_create_debug_dir(mdev); 248 mic_create_debug_dir(mdev);
264 249
265 mdev->miscdev.minor = MISC_DYNAMIC_MINOR;
266 snprintf(mdev->name, sizeof(mdev->name), "mic%d", mdev->id);
267 mdev->miscdev.name = mdev->name;
268 mdev->miscdev.fops = &mic_fops;
269 mdev->miscdev.parent = &mdev->pdev->dev;
270 rc = misc_register(&mdev->miscdev);
271 if (rc) {
272 dev_err(&pdev->dev, "misc_register err id %d rc %d\n",
273 mdev->id, rc);
274 goto cleanup_debug_dir;
275 }
276
277 mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops); 250 mdev->cosm_dev = cosm_register_device(&mdev->pdev->dev, &cosm_hw_ops);
278 if (IS_ERR(mdev->cosm_dev)) { 251 if (IS_ERR(mdev->cosm_dev)) {
279 rc = PTR_ERR(mdev->cosm_dev); 252 rc = PTR_ERR(mdev->cosm_dev);
280 dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc); 253 dev_err(&pdev->dev, "cosm_add_device failed rc %d\n", rc);
281 goto misc_dereg; 254 goto cleanup_debug_dir;
282 } 255 }
283 return 0; 256 return 0;
284misc_dereg:
285 misc_deregister(&mdev->miscdev);
286cleanup_debug_dir: 257cleanup_debug_dir:
287 mic_delete_debug_dir(mdev); 258 mic_delete_debug_dir(mdev);
288 mic_dp_uninit(mdev); 259 mic_dp_uninit(mdev);
@@ -323,7 +294,6 @@ static void mic_remove(struct pci_dev *pdev)
323 return; 294 return;
324 295
325 cosm_unregister_device(mdev->cosm_dev); 296 cosm_unregister_device(mdev->cosm_dev);
326 misc_deregister(&mdev->miscdev);
327 mic_delete_debug_dir(mdev); 297 mic_delete_debug_dir(mdev);
328 mic_dp_uninit(mdev); 298 mic_dp_uninit(mdev);
329 mic_smpt_uninit(mdev); 299 mic_smpt_uninit(mdev);
@@ -347,26 +317,17 @@ static int __init mic_init(void)
347{ 317{
348 int ret; 318 int ret;
349 319
350 ret = alloc_chrdev_region(&g_mic_devno, 0,
351 MIC_MAX_NUM_DEVS, mic_driver_name);
352 if (ret) {
353 pr_err("alloc_chrdev_region failed ret %d\n", ret);
354 goto error;
355 }
356
357 mic_init_debugfs(); 320 mic_init_debugfs();
358 ida_init(&g_mic_ida); 321 ida_init(&g_mic_ida);
359 ret = pci_register_driver(&mic_driver); 322 ret = pci_register_driver(&mic_driver);
360 if (ret) { 323 if (ret) {
361 pr_err("pci_register_driver failed ret %d\n", ret); 324 pr_err("pci_register_driver failed ret %d\n", ret);
362 goto cleanup_chrdev; 325 goto cleanup_debugfs;
363 } 326 }
364 return ret; 327 return 0;
365cleanup_chrdev: 328cleanup_debugfs:
366 ida_destroy(&g_mic_ida); 329 ida_destroy(&g_mic_ida);
367 mic_exit_debugfs(); 330 mic_exit_debugfs();
368 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
369error:
370 return ret; 331 return ret;
371} 332}
372 333
@@ -375,7 +336,6 @@ static void __exit mic_exit(void)
375 pci_unregister_driver(&mic_driver); 336 pci_unregister_driver(&mic_driver);
376 ida_destroy(&g_mic_ida); 337 ida_destroy(&g_mic_ida);
377 mic_exit_debugfs(); 338 mic_exit_debugfs();
378 unregister_chrdev_region(g_mic_devno, MIC_MAX_NUM_DEVS);
379} 339}
380 340
381module_init(mic_init); 341module_init(mic_init);
diff --git a/drivers/misc/mic/host/mic_virtio.c b/drivers/misc/mic/host/mic_virtio.c
deleted file mode 100644
index 58b107a24a8b..000000000000
--- a/drivers/misc/mic/host/mic_virtio.c
+++ /dev/null
@@ -1,811 +0,0 @@
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/pci.h>
22#include <linux/sched.h>
23#include <linux/uaccess.h>
24#include <linux/dmaengine.h>
25#include <linux/mic_common.h>
26#include "../common/mic_dev.h"
27#include "mic_device.h"
28#include "mic_smpt.h"
29#include "mic_virtio.h"
30
31/*
32 * Size of the internal buffer used during DMA's as an intermediate buffer
33 * for copy to/from user.
34 */
35#define MIC_INT_DMA_BUF_SIZE PAGE_ALIGN(64 * 1024ULL)
36
37static int mic_sync_dma(struct mic_device *mdev, dma_addr_t dst,
38 dma_addr_t src, size_t len)
39{
40 int err = 0;
41 struct dma_async_tx_descriptor *tx;
42 struct dma_chan *mic_ch = mdev->dma_ch[0];
43
44 if (!mic_ch) {
45 err = -EBUSY;
46 goto error;
47 }
48
49 tx = mic_ch->device->device_prep_dma_memcpy(mic_ch, dst, src, len,
50 DMA_PREP_FENCE);
51 if (!tx) {
52 err = -ENOMEM;
53 goto error;
54 } else {
55 dma_cookie_t cookie = tx->tx_submit(tx);
56
57 err = dma_submit_error(cookie);
58 if (err)
59 goto error;
60 err = dma_sync_wait(mic_ch, cookie);
61 }
62error:
63 if (err)
64 dev_err(&mdev->pdev->dev, "%s %d err %d\n",
65 __func__, __LINE__, err);
66 return err;
67}
68
69/*
70 * Initiates the copies across the PCIe bus from card memory to a user
71 * space buffer. When transfers are done using DMA, source/destination
72 * addresses and transfer length must follow the alignment requirements of
73 * the MIC DMA engine.
74 */
75static int mic_virtio_copy_to_user(struct mic_vdev *mvdev, void __user *ubuf,
76 size_t len, u64 daddr, size_t dlen,
77 int vr_idx)
78{
79 struct mic_device *mdev = mvdev->mdev;
80 void __iomem *dbuf = mdev->aper.va + daddr;
81 struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
82 size_t dma_alignment = 1 << mdev->dma_ch[0]->device->copy_align;
83 size_t dma_offset;
84 size_t partlen;
85 int err;
86
87 dma_offset = daddr - round_down(daddr, dma_alignment);
88 daddr -= dma_offset;
89 len += dma_offset;
90
91 while (len) {
92 partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
93
94 err = mic_sync_dma(mdev, mvr->buf_da, daddr,
95 ALIGN(partlen, dma_alignment));
96 if (err)
97 goto err;
98
99 if (copy_to_user(ubuf, mvr->buf + dma_offset,
100 partlen - dma_offset)) {
101 err = -EFAULT;
102 goto err;
103 }
104 daddr += partlen;
105 ubuf += partlen;
106 dbuf += partlen;
107 mvdev->in_bytes_dma += partlen;
108 mvdev->in_bytes += partlen;
109 len -= partlen;
110 dma_offset = 0;
111 }
112 return 0;
113err:
114 dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
115 return err;
116}
117
118/*
119 * Initiates copies across the PCIe bus from a user space buffer to card
120 * memory. When transfers are done using DMA, source/destination addresses
121 * and transfer length must follow the alignment requirements of the MIC
122 * DMA engine.
123 */
124static int mic_virtio_copy_from_user(struct mic_vdev *mvdev, void __user *ubuf,
125 size_t len, u64 daddr, size_t dlen,
126 int vr_idx)
127{
128 struct mic_device *mdev = mvdev->mdev;
129 void __iomem *dbuf = mdev->aper.va + daddr;
130 struct mic_vringh *mvr = &mvdev->mvr[vr_idx];
131 size_t dma_alignment = 1 << mdev->dma_ch[0]->device->copy_align;
132 size_t partlen;
133 int err;
134
135 if (daddr & (dma_alignment - 1)) {
136 mvdev->tx_dst_unaligned += len;
137 goto memcpy;
138 } else if (ALIGN(len, dma_alignment) > dlen) {
139 mvdev->tx_len_unaligned += len;
140 goto memcpy;
141 }
142
143 while (len) {
144 partlen = min_t(size_t, len, MIC_INT_DMA_BUF_SIZE);
145
146 if (copy_from_user(mvr->buf, ubuf, partlen)) {
147 err = -EFAULT;
148 goto err;
149 }
150 err = mic_sync_dma(mdev, daddr, mvr->buf_da,
151 ALIGN(partlen, dma_alignment));
152 if (err)
153 goto err;
154 daddr += partlen;
155 ubuf += partlen;
156 dbuf += partlen;
157 mvdev->out_bytes_dma += partlen;
158 mvdev->out_bytes += partlen;
159 len -= partlen;
160 }
161memcpy:
162 /*
163 * We are copying to IO below and should ideally use something
164 * like copy_from_user_toio(..) if it existed.
165 */
166 if (copy_from_user((void __force *)dbuf, ubuf, len)) {
167 err = -EFAULT;
168 goto err;
169 }
170 mvdev->out_bytes += len;
171 return 0;
172err:
173 dev_err(mic_dev(mvdev), "%s %d err %d\n", __func__, __LINE__, err);
174 return err;
175}
176
177#define MIC_VRINGH_READ true
178
179/* The function to call to notify the card about added buffers */
180static void mic_notify(struct vringh *vrh)
181{
182 struct mic_vringh *mvrh = container_of(vrh, struct mic_vringh, vrh);
183 struct mic_vdev *mvdev = mvrh->mvdev;
184 s8 db = mvdev->dc->h2c_vdev_db;
185
186 if (db != -1)
187 mvdev->mdev->ops->send_intr(mvdev->mdev, db);
188}
189
190/* Determine the total number of bytes consumed in a VRINGH KIOV */
191static inline u32 mic_vringh_iov_consumed(struct vringh_kiov *iov)
192{
193 int i;
194 u32 total = iov->consumed;
195
196 for (i = 0; i < iov->i; i++)
197 total += iov->iov[i].iov_len;
198 return total;
199}
200
201/*
202 * Traverse the VRINGH KIOV and issue the APIs to trigger the copies.
203 * This API is heavily based on the vringh_iov_xfer(..) implementation
204 * in vringh.c. The reason we cannot reuse vringh_iov_pull_kern(..)
205 * and vringh_iov_push_kern(..) directly is because there is no
206 * way to override the VRINGH xfer(..) routines as of v3.10.
207 */
208static int mic_vringh_copy(struct mic_vdev *mvdev, struct vringh_kiov *iov,
209 void __user *ubuf, size_t len, bool read, int vr_idx,
210 size_t *out_len)
211{
212 int ret = 0;
213 size_t partlen, tot_len = 0;
214
215 while (len && iov->i < iov->used) {
216 partlen = min(iov->iov[iov->i].iov_len, len);
217 if (read)
218 ret = mic_virtio_copy_to_user(mvdev, ubuf, partlen,
219 (u64)iov->iov[iov->i].iov_base,
220 iov->iov[iov->i].iov_len,
221 vr_idx);
222 else
223 ret = mic_virtio_copy_from_user(mvdev, ubuf, partlen,
224 (u64)iov->iov[iov->i].iov_base,
225 iov->iov[iov->i].iov_len,
226 vr_idx);
227 if (ret) {
228 dev_err(mic_dev(mvdev), "%s %d err %d\n",
229 __func__, __LINE__, ret);
230 break;
231 }
232 len -= partlen;
233 ubuf += partlen;
234 tot_len += partlen;
235 iov->consumed += partlen;
236 iov->iov[iov->i].iov_len -= partlen;
237 iov->iov[iov->i].iov_base += partlen;
238 if (!iov->iov[iov->i].iov_len) {
239 /* Fix up old iov element then increment. */
240 iov->iov[iov->i].iov_len = iov->consumed;
241 iov->iov[iov->i].iov_base -= iov->consumed;
242
243 iov->consumed = 0;
244 iov->i++;
245 }
246 }
247 *out_len = tot_len;
248 return ret;
249}
250
251/*
252 * Use the standard VRINGH infrastructure in the kernel to fetch new
253 * descriptors, initiate the copies and update the used ring.
254 */
255static int _mic_virtio_copy(struct mic_vdev *mvdev,
256 struct mic_copy_desc *copy)
257{
258 int ret = 0;
259 u32 iovcnt = copy->iovcnt;
260 struct iovec iov;
261 struct iovec __user *u_iov = copy->iov;
262 void __user *ubuf = NULL;
263 struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
264 struct vringh_kiov *riov = &mvr->riov;
265 struct vringh_kiov *wiov = &mvr->wiov;
266 struct vringh *vrh = &mvr->vrh;
267 u16 *head = &mvr->head;
268 struct mic_vring *vr = &mvr->vring;
269 size_t len = 0, out_len;
270
271 copy->out_len = 0;
272 /* Fetch a new IOVEC if all previous elements have been processed */
273 if (riov->i == riov->used && wiov->i == wiov->used) {
274 ret = vringh_getdesc_kern(vrh, riov, wiov,
275 head, GFP_KERNEL);
276 /* Check if there are available descriptors */
277 if (ret <= 0)
278 return ret;
279 }
280 while (iovcnt) {
281 if (!len) {
282 /* Copy over a new iovec from user space. */
283 ret = copy_from_user(&iov, u_iov, sizeof(*u_iov));
284 if (ret) {
285 ret = -EINVAL;
286 dev_err(mic_dev(mvdev), "%s %d err %d\n",
287 __func__, __LINE__, ret);
288 break;
289 }
290 len = iov.iov_len;
291 ubuf = iov.iov_base;
292 }
293 /* Issue all the read descriptors first */
294 ret = mic_vringh_copy(mvdev, riov, ubuf, len, MIC_VRINGH_READ,
295 copy->vr_idx, &out_len);
296 if (ret) {
297 dev_err(mic_dev(mvdev), "%s %d err %d\n",
298 __func__, __LINE__, ret);
299 break;
300 }
301 len -= out_len;
302 ubuf += out_len;
303 copy->out_len += out_len;
304 /* Issue the write descriptors next */
305 ret = mic_vringh_copy(mvdev, wiov, ubuf, len, !MIC_VRINGH_READ,
306 copy->vr_idx, &out_len);
307 if (ret) {
308 dev_err(mic_dev(mvdev), "%s %d err %d\n",
309 __func__, __LINE__, ret);
310 break;
311 }
312 len -= out_len;
313 ubuf += out_len;
314 copy->out_len += out_len;
315 if (!len) {
316 /* One user space iovec is now completed */
317 iovcnt--;
318 u_iov++;
319 }
320 /* Exit loop if all elements in KIOVs have been processed. */
321 if (riov->i == riov->used && wiov->i == wiov->used)
322 break;
323 }
324 /*
325 * Update the used ring if a descriptor was available and some data was
326 * copied in/out and the user asked for a used ring update.
327 */
328 if (*head != USHRT_MAX && copy->out_len && copy->update_used) {
329 u32 total = 0;
330
331 /* Determine the total data consumed */
332 total += mic_vringh_iov_consumed(riov);
333 total += mic_vringh_iov_consumed(wiov);
334 vringh_complete_kern(vrh, *head, total);
335 *head = USHRT_MAX;
336 if (vringh_need_notify_kern(vrh) > 0)
337 vringh_notify(vrh);
338 vringh_kiov_cleanup(riov);
339 vringh_kiov_cleanup(wiov);
340 /* Update avail idx for user space */
341 vr->info->avail_idx = vrh->last_avail_idx;
342 }
343 return ret;
344}
345
346static inline int mic_verify_copy_args(struct mic_vdev *mvdev,
347 struct mic_copy_desc *copy)
348{
349 if (copy->vr_idx >= mvdev->dd->num_vq) {
350 dev_err(mic_dev(mvdev), "%s %d err %d\n",
351 __func__, __LINE__, -EINVAL);
352 return -EINVAL;
353 }
354 return 0;
355}
356
357/* Copy a specified number of virtio descriptors in a chain */
358int mic_virtio_copy_desc(struct mic_vdev *mvdev,
359 struct mic_copy_desc *copy)
360{
361 int err;
362 struct mic_vringh *mvr = &mvdev->mvr[copy->vr_idx];
363
364 err = mic_verify_copy_args(mvdev, copy);
365 if (err)
366 return err;
367
368 mutex_lock(&mvr->vr_mutex);
369 if (!mic_vdevup(mvdev)) {
370 err = -ENODEV;
371 dev_err(mic_dev(mvdev), "%s %d err %d\n",
372 __func__, __LINE__, err);
373 goto err;
374 }
375 err = _mic_virtio_copy(mvdev, copy);
376 if (err) {
377 dev_err(mic_dev(mvdev), "%s %d err %d\n",
378 __func__, __LINE__, err);
379 }
380err:
381 mutex_unlock(&mvr->vr_mutex);
382 return err;
383}
384
385static void mic_virtio_init_post(struct mic_vdev *mvdev)
386{
387 struct mic_vqconfig *vqconfig = mic_vq_config(mvdev->dd);
388 int i;
389
390 for (i = 0; i < mvdev->dd->num_vq; i++) {
391 if (!le64_to_cpu(vqconfig[i].used_address)) {
392 dev_warn(mic_dev(mvdev), "used_address zero??\n");
393 continue;
394 }
395 mvdev->mvr[i].vrh.vring.used =
396 (void __force *)mvdev->mdev->aper.va +
397 le64_to_cpu(vqconfig[i].used_address);
398 }
399
400 mvdev->dc->used_address_updated = 0;
401
402 dev_dbg(mic_dev(mvdev), "%s: device type %d LINKUP\n",
403 __func__, mvdev->virtio_id);
404}
405
406static inline void mic_virtio_device_reset(struct mic_vdev *mvdev)
407{
408 int i;
409
410 dev_dbg(mic_dev(mvdev), "%s: status %d device type %d RESET\n",
411 __func__, mvdev->dd->status, mvdev->virtio_id);
412
413 for (i = 0; i < mvdev->dd->num_vq; i++)
414 /*
415 * Avoid lockdep false positive. The + 1 is for the mic
416 * mutex which is held in the reset devices code path.
417 */
418 mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
419
420 /* 0 status means "reset" */
421 mvdev->dd->status = 0;
422 mvdev->dc->vdev_reset = 0;
423 mvdev->dc->host_ack = 1;
424
425 for (i = 0; i < mvdev->dd->num_vq; i++) {
426 struct vringh *vrh = &mvdev->mvr[i].vrh;
427 mvdev->mvr[i].vring.info->avail_idx = 0;
428 vrh->completed = 0;
429 vrh->last_avail_idx = 0;
430 vrh->last_used_idx = 0;
431 }
432
433 for (i = 0; i < mvdev->dd->num_vq; i++)
434 mutex_unlock(&mvdev->mvr[i].vr_mutex);
435}
436
437void mic_virtio_reset_devices(struct mic_device *mdev)
438{
439 struct list_head *pos, *tmp;
440 struct mic_vdev *mvdev;
441
442 dev_dbg(&mdev->pdev->dev, "%s\n", __func__);
443
444 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
445 mvdev = list_entry(pos, struct mic_vdev, list);
446 mic_virtio_device_reset(mvdev);
447 mvdev->poll_wake = 1;
448 wake_up(&mvdev->waitq);
449 }
450}
451
452void mic_bh_handler(struct work_struct *work)
453{
454 struct mic_vdev *mvdev = container_of(work, struct mic_vdev,
455 virtio_bh_work);
456
457 if (mvdev->dc->used_address_updated)
458 mic_virtio_init_post(mvdev);
459
460 if (mvdev->dc->vdev_reset)
461 mic_virtio_device_reset(mvdev);
462
463 mvdev->poll_wake = 1;
464 wake_up(&mvdev->waitq);
465}
466
467static irqreturn_t mic_virtio_intr_handler(int irq, void *data)
468{
469 struct mic_vdev *mvdev = data;
470 struct mic_device *mdev = mvdev->mdev;
471
472 mdev->ops->intr_workarounds(mdev);
473 schedule_work(&mvdev->virtio_bh_work);
474 return IRQ_HANDLED;
475}
476
477int mic_virtio_config_change(struct mic_vdev *mvdev,
478 void __user *argp)
479{
480 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
481 int ret = 0, retry, i;
482 struct mic_bootparam *bootparam = mvdev->mdev->dp;
483 s8 db = bootparam->h2c_config_db;
484
485 mutex_lock(&mvdev->mdev->mic_mutex);
486 for (i = 0; i < mvdev->dd->num_vq; i++)
487 mutex_lock_nested(&mvdev->mvr[i].vr_mutex, i + 1);
488
489 if (db == -1 || mvdev->dd->type == -1) {
490 ret = -EIO;
491 goto exit;
492 }
493
494 if (copy_from_user(mic_vq_configspace(mvdev->dd),
495 argp, mvdev->dd->config_len)) {
496 dev_err(mic_dev(mvdev), "%s %d err %d\n",
497 __func__, __LINE__, -EFAULT);
498 ret = -EFAULT;
499 goto exit;
500 }
501 mvdev->dc->config_change = MIC_VIRTIO_PARAM_CONFIG_CHANGED;
502 mvdev->mdev->ops->send_intr(mvdev->mdev, db);
503
504 for (retry = 100; retry--;) {
505 ret = wait_event_timeout(wake,
506 mvdev->dc->guest_ack, msecs_to_jiffies(100));
507 if (ret)
508 break;
509 }
510
511 dev_dbg(mic_dev(mvdev),
512 "%s %d retry: %d\n", __func__, __LINE__, retry);
513 mvdev->dc->config_change = 0;
514 mvdev->dc->guest_ack = 0;
515exit:
516 for (i = 0; i < mvdev->dd->num_vq; i++)
517 mutex_unlock(&mvdev->mvr[i].vr_mutex);
518 mutex_unlock(&mvdev->mdev->mic_mutex);
519 return ret;
520}
521
522static int mic_copy_dp_entry(struct mic_vdev *mvdev,
523 void __user *argp,
524 __u8 *type,
525 struct mic_device_desc **devpage)
526{
527 struct mic_device *mdev = mvdev->mdev;
528 struct mic_device_desc dd, *dd_config, *devp;
529 struct mic_vqconfig *vqconfig;
530 int ret = 0, i;
531 bool slot_found = false;
532
533 if (copy_from_user(&dd, argp, sizeof(dd))) {
534 dev_err(mic_dev(mvdev), "%s %d err %d\n",
535 __func__, __LINE__, -EFAULT);
536 return -EFAULT;
537 }
538
539 if (mic_aligned_desc_size(&dd) > MIC_MAX_DESC_BLK_SIZE ||
540 dd.num_vq > MIC_MAX_VRINGS) {
541 dev_err(mic_dev(mvdev), "%s %d err %d\n",
542 __func__, __LINE__, -EINVAL);
543 return -EINVAL;
544 }
545
546 dd_config = kmalloc(mic_desc_size(&dd), GFP_KERNEL);
547 if (dd_config == NULL) {
548 dev_err(mic_dev(mvdev), "%s %d err %d\n",
549 __func__, __LINE__, -ENOMEM);
550 return -ENOMEM;
551 }
552 if (copy_from_user(dd_config, argp, mic_desc_size(&dd))) {
553 ret = -EFAULT;
554 dev_err(mic_dev(mvdev), "%s %d err %d\n",
555 __func__, __LINE__, ret);
556 goto exit;
557 }
558
559 vqconfig = mic_vq_config(dd_config);
560 for (i = 0; i < dd.num_vq; i++) {
561 if (le16_to_cpu(vqconfig[i].num) > MIC_MAX_VRING_ENTRIES) {
562 ret = -EINVAL;
563 dev_err(mic_dev(mvdev), "%s %d err %d\n",
564 __func__, __LINE__, ret);
565 goto exit;
566 }
567 }
568
569 /* Find the first free device page entry */
570 for (i = sizeof(struct mic_bootparam);
571 i < MIC_DP_SIZE - mic_total_desc_size(dd_config);
572 i += mic_total_desc_size(devp)) {
573 devp = mdev->dp + i;
574 if (devp->type == 0 || devp->type == -1) {
575 slot_found = true;
576 break;
577 }
578 }
579 if (!slot_found) {
580 ret = -EINVAL;
581 dev_err(mic_dev(mvdev), "%s %d err %d\n",
582 __func__, __LINE__, ret);
583 goto exit;
584 }
585 /*
586 * Save off the type before doing the memcpy. Type will be set in the
587 * end after completing all initialization for the new device.
588 */
589 *type = dd_config->type;
590 dd_config->type = 0;
591 memcpy(devp, dd_config, mic_desc_size(dd_config));
592
593 *devpage = devp;
594exit:
595 kfree(dd_config);
596 return ret;
597}
598
599static void mic_init_device_ctrl(struct mic_vdev *mvdev,
600 struct mic_device_desc *devpage)
601{
602 struct mic_device_ctrl *dc;
603
604 dc = (void *)devpage + mic_aligned_desc_size(devpage);
605
606 dc->config_change = 0;
607 dc->guest_ack = 0;
608 dc->vdev_reset = 0;
609 dc->host_ack = 0;
610 dc->used_address_updated = 0;
611 dc->c2h_vdev_db = -1;
612 dc->h2c_vdev_db = -1;
613 mvdev->dc = dc;
614}
615
616int mic_virtio_add_device(struct mic_vdev *mvdev,
617 void __user *argp)
618{
619 struct mic_device *mdev = mvdev->mdev;
620 struct mic_device_desc *dd = NULL;
621 struct mic_vqconfig *vqconfig;
622 int vr_size, i, j, ret;
623 u8 type = 0;
624 s8 db;
625 char irqname[10];
626 struct mic_bootparam *bootparam = mdev->dp;
627 u16 num;
628 dma_addr_t vr_addr;
629
630 mutex_lock(&mdev->mic_mutex);
631
632 ret = mic_copy_dp_entry(mvdev, argp, &type, &dd);
633 if (ret) {
634 mutex_unlock(&mdev->mic_mutex);
635 return ret;
636 }
637
638 mic_init_device_ctrl(mvdev, dd);
639
640 mvdev->dd = dd;
641 mvdev->virtio_id = type;
642 vqconfig = mic_vq_config(dd);
643 INIT_WORK(&mvdev->virtio_bh_work, mic_bh_handler);
644
645 for (i = 0; i < dd->num_vq; i++) {
646 struct mic_vringh *mvr = &mvdev->mvr[i];
647 struct mic_vring *vr = &mvdev->mvr[i].vring;
648 num = le16_to_cpu(vqconfig[i].num);
649 mutex_init(&mvr->vr_mutex);
650 vr_size = PAGE_ALIGN(vring_size(num, MIC_VIRTIO_RING_ALIGN) +
651 sizeof(struct _mic_vring_info));
652 vr->va = (void *)
653 __get_free_pages(GFP_KERNEL | __GFP_ZERO,
654 get_order(vr_size));
655 if (!vr->va) {
656 ret = -ENOMEM;
657 dev_err(mic_dev(mvdev), "%s %d err %d\n",
658 __func__, __LINE__, ret);
659 goto err;
660 }
661 vr->len = vr_size;
662 vr->info = vr->va + vring_size(num, MIC_VIRTIO_RING_ALIGN);
663 vr->info->magic = cpu_to_le32(MIC_MAGIC + mvdev->virtio_id + i);
664 vr_addr = mic_map_single(mdev, vr->va, vr_size);
665 if (mic_map_error(vr_addr)) {
666 free_pages((unsigned long)vr->va, get_order(vr_size));
667 ret = -ENOMEM;
668 dev_err(mic_dev(mvdev), "%s %d err %d\n",
669 __func__, __LINE__, ret);
670 goto err;
671 }
672 vqconfig[i].address = cpu_to_le64(vr_addr);
673
674 vring_init(&vr->vr, num, vr->va, MIC_VIRTIO_RING_ALIGN);
675 ret = vringh_init_kern(&mvr->vrh,
676 *(u32 *)mic_vq_features(mvdev->dd), num, false,
677 vr->vr.desc, vr->vr.avail, vr->vr.used);
678 if (ret) {
679 dev_err(mic_dev(mvdev), "%s %d err %d\n",
680 __func__, __LINE__, ret);
681 goto err;
682 }
683 vringh_kiov_init(&mvr->riov, NULL, 0);
684 vringh_kiov_init(&mvr->wiov, NULL, 0);
685 mvr->head = USHRT_MAX;
686 mvr->mvdev = mvdev;
687 mvr->vrh.notify = mic_notify;
688 dev_dbg(&mdev->pdev->dev,
689 "%s %d index %d va %p info %p vr_size 0x%x\n",
690 __func__, __LINE__, i, vr->va, vr->info, vr_size);
691 mvr->buf = (void *)__get_free_pages(GFP_KERNEL,
692 get_order(MIC_INT_DMA_BUF_SIZE));
693 mvr->buf_da = mic_map_single(mvdev->mdev, mvr->buf,
694 MIC_INT_DMA_BUF_SIZE);
695 }
696
697 snprintf(irqname, sizeof(irqname), "mic%dvirtio%d", mdev->id,
698 mvdev->virtio_id);
699 mvdev->virtio_db = mic_next_db(mdev);
700 mvdev->virtio_cookie = mic_request_threaded_irq(mdev,
701 mic_virtio_intr_handler,
702 NULL, irqname, mvdev,
703 mvdev->virtio_db, MIC_INTR_DB);
704 if (IS_ERR(mvdev->virtio_cookie)) {
705 ret = PTR_ERR(mvdev->virtio_cookie);
706 dev_dbg(&mdev->pdev->dev, "request irq failed\n");
707 goto err;
708 }
709
710 mvdev->dc->c2h_vdev_db = mvdev->virtio_db;
711
712 list_add_tail(&mvdev->list, &mdev->vdev_list);
713 /*
714 * Order the type update with previous stores. This write barrier
715 * is paired with the corresponding read barrier before the uncached
716 * system memory read of the type, on the card while scanning the
717 * device page.
718 */
719 smp_wmb();
720 dd->type = type;
721
722 dev_dbg(&mdev->pdev->dev, "Added virtio device id %d\n", dd->type);
723
724 db = bootparam->h2c_config_db;
725 if (db != -1)
726 mdev->ops->send_intr(mdev, db);
727 mutex_unlock(&mdev->mic_mutex);
728 return 0;
729err:
730 vqconfig = mic_vq_config(dd);
731 for (j = 0; j < i; j++) {
732 struct mic_vringh *mvr = &mvdev->mvr[j];
733 mic_unmap_single(mdev, le64_to_cpu(vqconfig[j].address),
734 mvr->vring.len);
735 free_pages((unsigned long)mvr->vring.va,
736 get_order(mvr->vring.len));
737 }
738 mutex_unlock(&mdev->mic_mutex);
739 return ret;
740}
741
742void mic_virtio_del_device(struct mic_vdev *mvdev)
743{
744 struct list_head *pos, *tmp;
745 struct mic_vdev *tmp_mvdev;
746 struct mic_device *mdev = mvdev->mdev;
747 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wake);
748 int i, ret, retry;
749 struct mic_vqconfig *vqconfig;
750 struct mic_bootparam *bootparam = mdev->dp;
751 s8 db;
752
753 mutex_lock(&mdev->mic_mutex);
754 db = bootparam->h2c_config_db;
755 if (db == -1)
756 goto skip_hot_remove;
757 dev_dbg(&mdev->pdev->dev,
758 "Requesting hot remove id %d\n", mvdev->virtio_id);
759 mvdev->dc->config_change = MIC_VIRTIO_PARAM_DEV_REMOVE;
760 mdev->ops->send_intr(mdev, db);
761 for (retry = 100; retry--;) {
762 ret = wait_event_timeout(wake,
763 mvdev->dc->guest_ack, msecs_to_jiffies(100));
764 if (ret)
765 break;
766 }
767 dev_dbg(&mdev->pdev->dev,
768 "Device id %d config_change %d guest_ack %d retry %d\n",
769 mvdev->virtio_id, mvdev->dc->config_change,
770 mvdev->dc->guest_ack, retry);
771 mvdev->dc->config_change = 0;
772 mvdev->dc->guest_ack = 0;
773skip_hot_remove:
774 mic_free_irq(mdev, mvdev->virtio_cookie, mvdev);
775 flush_work(&mvdev->virtio_bh_work);
776 vqconfig = mic_vq_config(mvdev->dd);
777 for (i = 0; i < mvdev->dd->num_vq; i++) {
778 struct mic_vringh *mvr = &mvdev->mvr[i];
779
780 mic_unmap_single(mvdev->mdev, mvr->buf_da,
781 MIC_INT_DMA_BUF_SIZE);
782 free_pages((unsigned long)mvr->buf,
783 get_order(MIC_INT_DMA_BUF_SIZE));
784 vringh_kiov_cleanup(&mvr->riov);
785 vringh_kiov_cleanup(&mvr->wiov);
786 mic_unmap_single(mdev, le64_to_cpu(vqconfig[i].address),
787 mvr->vring.len);
788 free_pages((unsigned long)mvr->vring.va,
789 get_order(mvr->vring.len));
790 }
791
792 list_for_each_safe(pos, tmp, &mdev->vdev_list) {
793 tmp_mvdev = list_entry(pos, struct mic_vdev, list);
794 if (tmp_mvdev == mvdev) {
795 list_del(pos);
796 dev_dbg(&mdev->pdev->dev,
797 "Removing virtio device id %d\n",
798 mvdev->virtio_id);
799 break;
800 }
801 }
802 /*
803 * Order the type update with previous stores. This write barrier
804 * is paired with the corresponding read barrier before the uncached
805 * system memory read of the type, on the card while scanning the
806 * device page.
807 */
808 smp_wmb();
809 mvdev->dd->type = -1;
810 mutex_unlock(&mdev->mic_mutex);
811}
diff --git a/drivers/misc/mic/host/mic_virtio.h b/drivers/misc/mic/host/mic_virtio.h
deleted file mode 100644
index a80631f2790d..000000000000
--- a/drivers/misc/mic/host/mic_virtio.h
+++ /dev/null
@@ -1,155 +0,0 @@
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#ifndef MIC_VIRTIO_H
22#define MIC_VIRTIO_H
23
24#include <linux/virtio_config.h>
25#include <linux/mic_ioctl.h>
26
27/*
28 * Note on endianness.
29 * 1. Host can be both BE or LE
30 * 2. Guest/card is LE. Host uses le_to_cpu to access desc/avail
31 * rings and ioreadXX/iowriteXX to access used ring.
32 * 3. Device page exposed by host to guest contains LE values. Guest
33 * accesses these using ioreadXX/iowriteXX etc. This way in general we
34 * obey the virtio spec according to which guest works with native
35 * endianness and host is aware of guest endianness and does all
36 * required endianness conversion.
37 * 4. Data provided from user space to guest (in ADD_DEVICE and
38 * CONFIG_CHANGE ioctl's) is not interpreted by the driver and should be
39 * in guest endianness.
40 */
41
42/**
43 * struct mic_vringh - Virtio ring host information.
44 *
45 * @vring: The MIC vring used for setting up user space mappings.
46 * @vrh: The host VRINGH used for accessing the card vrings.
47 * @riov: The VRINGH read kernel IOV.
48 * @wiov: The VRINGH write kernel IOV.
49 * @vr_mutex: Mutex for synchronizing access to the VRING.
50 * @buf: Temporary kernel buffer used to copy in/out data
51 * from/to the card via DMA.
52 * @buf_da: dma address of buf.
53 * @mvdev: Back pointer to MIC virtio device for vringh_notify(..).
54 * @head: The VRINGH head index address passed to vringh_getdesc_kern(..).
55 */
56struct mic_vringh {
57 struct mic_vring vring;
58 struct vringh vrh;
59 struct vringh_kiov riov;
60 struct vringh_kiov wiov;
61 struct mutex vr_mutex;
62 void *buf;
63 dma_addr_t buf_da;
64 struct mic_vdev *mvdev;
65 u16 head;
66};
67
68/**
69 * struct mic_vdev - Host information for a card Virtio device.
70 *
71 * @virtio_id - Virtio device id.
72 * @waitq - Waitqueue to allow ring3 apps to poll.
73 * @mdev - Back pointer to host MIC device.
74 * @poll_wake - Used for waking up threads blocked in poll.
75 * @out_bytes - Debug stats for number of bytes copied from host to card.
76 * @in_bytes - Debug stats for number of bytes copied from card to host.
77 * @out_bytes_dma - Debug stats for number of bytes copied from host to card
78 * using DMA.
79 * @in_bytes_dma - Debug stats for number of bytes copied from card to host
80 * using DMA.
81 * @tx_len_unaligned - Debug stats for number of bytes copied to the card where
82 * the transfer length did not have the required DMA alignment.
83 * @tx_dst_unaligned - Debug stats for number of bytes copied where the
84 * destination address on the card did not have the required DMA alignment.
85 * @mvr - Store per VRING data structures.
86 * @virtio_bh_work - Work struct used to schedule virtio bottom half handling.
87 * @dd - Virtio device descriptor.
88 * @dc - Virtio device control fields.
89 * @list - List of Virtio devices.
90 * @virtio_db - The doorbell used by the card to interrupt the host.
91 * @virtio_cookie - The cookie returned while requesting interrupts.
92 */
93struct mic_vdev {
94 int virtio_id;
95 wait_queue_head_t waitq;
96 struct mic_device *mdev;
97 int poll_wake;
98 unsigned long out_bytes;
99 unsigned long in_bytes;
100 unsigned long out_bytes_dma;
101 unsigned long in_bytes_dma;
102 unsigned long tx_len_unaligned;
103 unsigned long tx_dst_unaligned;
104 struct mic_vringh mvr[MIC_MAX_VRINGS];
105 struct work_struct virtio_bh_work;
106 struct mic_device_desc *dd;
107 struct mic_device_ctrl *dc;
108 struct list_head list;
109 int virtio_db;
110 struct mic_irq *virtio_cookie;
111};
112
113void mic_virtio_uninit(struct mic_device *mdev);
114int mic_virtio_add_device(struct mic_vdev *mvdev,
115 void __user *argp);
116void mic_virtio_del_device(struct mic_vdev *mvdev);
117int mic_virtio_config_change(struct mic_vdev *mvdev,
118 void __user *argp);
119int mic_virtio_copy_desc(struct mic_vdev *mvdev,
120 struct mic_copy_desc *request);
121void mic_virtio_reset_devices(struct mic_device *mdev);
122void mic_bh_handler(struct work_struct *work);
123
124/* Helper API to obtain the MIC PCIe device */
125static inline struct device *mic_dev(struct mic_vdev *mvdev)
126{
127 return &mvdev->mdev->pdev->dev;
128}
129
130/* Helper API to check if a virtio device is initialized */
131static inline int mic_vdev_inited(struct mic_vdev *mvdev)
132{
133 /* Device has not been created yet */
134 if (!mvdev->dd || !mvdev->dd->type) {
135 dev_err(mic_dev(mvdev), "%s %d err %d\n",
136 __func__, __LINE__, -EINVAL);
137 return -EINVAL;
138 }
139
140 /* Device has been removed/deleted */
141 if (mvdev->dd->type == -1) {
142 dev_err(mic_dev(mvdev), "%s %d err %d\n",
143 __func__, __LINE__, -ENODEV);
144 return -ENODEV;
145 }
146
147 return 0;
148}
149
150/* Helper API to check if a virtio device is running */
151static inline bool mic_vdevup(struct mic_vdev *mvdev)
152{
153 return !!mvdev->dd->status;
154}
155#endif