summaryrefslogtreecommitdiffstats
path: root/drivers/misc/mic
diff options
context:
space:
mode:
authorAshutosh Dixit <ashutosh.dixit@intel.com>2013-09-05 19:42:28 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-09-26 16:52:24 -0400
commit2141c7c5ee677014023cb50c793f91e85f44d2ea (patch)
tree153d09d3da1c4d42966f59408a7b8bf32d317513 /drivers/misc/mic
parentf69bcbf3b4c4b333dcd7a48eaf868bf0c88edab5 (diff)
Intel MIC Card Driver Changes for Virtio Devices.
This patch introduces the card "Virtio over PCIe" interface for Intel MIC. It allows virtio drivers on the card to communicate with their user space backends on the host via a device page. Ring 3 apps on the host can add, remove and configure virtio devices. A thin MIC specific virtio_config_ops is implemented which is borrowed heavily from previous similar implementations in lguest and s390 @ drivers/lguest/lguest_device.c drivers/s390/kvm/kvm_virtio.c Co-author: Sudeep Dutt <sudeep.dutt@intel.com> Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com> Signed-off-by: Caz Yokoyama <Caz.Yokoyama@intel.com> Signed-off-by: Dasaratharaman Chandramouli <dasaratharaman.chandramouli@intel.com> Signed-off-by: Nikhil Rao <nikhil.rao@intel.com> Signed-off-by: Harshavardhan R Kharche <harshavardhan.r.kharche@intel.com> Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com> Acked-by: Yaozu (Eddie) Dong <eddie.dong@intel.com> Reviewed-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mic')
-rw-r--r--drivers/misc/mic/Kconfig1
-rw-r--r--drivers/misc/mic/card/Makefile1
-rw-r--r--drivers/misc/mic/card/mic_device.c7
-rw-r--r--drivers/misc/mic/card/mic_virtio.c631
-rw-r--r--drivers/misc/mic/card/mic_virtio.h77
5 files changed, 717 insertions, 0 deletions
diff --git a/drivers/misc/mic/Kconfig b/drivers/misc/mic/Kconfig
index 01f1a4a84c63..d453768e9cee 100644
--- a/drivers/misc/mic/Kconfig
+++ b/drivers/misc/mic/Kconfig
@@ -24,6 +24,7 @@ comment "Intel MIC Card Driver"
24config INTEL_MIC_CARD 24config INTEL_MIC_CARD
25 tristate "Intel MIC Card Driver" 25 tristate "Intel MIC Card Driver"
26 depends on 64BIT 26 depends on 64BIT
27 select VIRTIO
27 default N 28 default N
28 help 29 help
29 This enables card driver support for the Intel Many Integrated 30 This enables card driver support for the Intel Many Integrated
diff --git a/drivers/misc/mic/card/Makefile b/drivers/misc/mic/card/Makefile
index 6e9675e12a09..69d58bef92ce 100644
--- a/drivers/misc/mic/card/Makefile
+++ b/drivers/misc/mic/card/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_INTEL_MIC_CARD) += mic_card.o
8mic_card-y += mic_x100.o 8mic_card-y += mic_x100.o
9mic_card-y += mic_device.o 9mic_card-y += mic_device.o
10mic_card-y += mic_debugfs.o 10mic_card-y += mic_debugfs.o
11mic_card-y += mic_virtio.o
diff --git a/drivers/misc/mic/card/mic_device.c b/drivers/misc/mic/card/mic_device.c
index 3c5c302dba41..4125217579af 100644
--- a/drivers/misc/mic/card/mic_device.c
+++ b/drivers/misc/mic/card/mic_device.c
@@ -32,6 +32,7 @@
32#include <linux/mic_common.h> 32#include <linux/mic_common.h>
33#include "../common/mic_device.h" 33#include "../common/mic_device.h"
34#include "mic_device.h" 34#include "mic_device.h"
35#include "mic_virtio.h"
35 36
36static struct mic_driver *g_drv; 37static struct mic_driver *g_drv;
37static struct mic_irq *shutdown_cookie; 38static struct mic_irq *shutdown_cookie;
@@ -265,10 +266,15 @@ int __init mic_driver_init(struct mic_driver *mdrv)
265 rc = mic_shutdown_init(); 266 rc = mic_shutdown_init();
266 if (rc) 267 if (rc)
267 goto irq_uninit; 268 goto irq_uninit;
269 rc = mic_devices_init(mdrv);
270 if (rc)
271 goto shutdown_uninit;
268 mic_create_card_debug_dir(mdrv); 272 mic_create_card_debug_dir(mdrv);
269 atomic_notifier_chain_register(&panic_notifier_list, &mic_panic); 273 atomic_notifier_chain_register(&panic_notifier_list, &mic_panic);
270done: 274done:
271 return rc; 275 return rc;
276shutdown_uninit:
277 mic_shutdown_uninit();
272irq_uninit: 278irq_uninit:
273 mic_uninit_irq(); 279 mic_uninit_irq();
274dp_uninit: 280dp_uninit:
@@ -286,6 +292,7 @@ put:
286void mic_driver_uninit(struct mic_driver *mdrv) 292void mic_driver_uninit(struct mic_driver *mdrv)
287{ 293{
288 mic_delete_card_debug_dir(mdrv); 294 mic_delete_card_debug_dir(mdrv);
295 mic_devices_uninit(mdrv);
289 /* 296 /*
290 * Inform the host about the shutdown status i.e. poweroff/restart etc. 297 * Inform the host about the shutdown status i.e. poweroff/restart etc.
291 * The module cannot be unloaded so the only code path to call 298 * The module cannot be unloaded so the only code path to call
diff --git a/drivers/misc/mic/card/mic_virtio.c b/drivers/misc/mic/card/mic_virtio.c
new file mode 100644
index 000000000000..38275c1b9e03
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.c
@@ -0,0 +1,631 @@
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 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Adapted from:
25 *
26 * virtio for kvm on s390
27 *
28 * Copyright IBM Corp. 2008
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License (version 2 only)
32 * as published by the Free Software Foundation.
33 *
34 * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
35 *
36 * Intel MIC Card driver.
37 *
38 */
39#include <linux/delay.h>
40#include <linux/slab.h>
41#include <linux/virtio_config.h>
42
43#include "../common/mic_device.h"
44#include "mic_virtio.h"
45
46#define VIRTIO_SUBCODE_64 0x0D00
47
48#define MIC_MAX_VRINGS 4
49struct mic_vdev {
50 struct virtio_device vdev;
51 struct mic_device_desc __iomem *desc;
52 struct mic_device_ctrl __iomem *dc;
53 struct mic_device *mdev;
54 void __iomem *vr[MIC_MAX_VRINGS];
55 int used_size[MIC_MAX_VRINGS];
56 struct completion reset_done;
57 struct mic_irq *virtio_cookie;
58 int c2h_vdev_db;
59};
60
61static struct mic_irq *virtio_config_cookie;
62#define to_micvdev(vd) container_of(vd, struct mic_vdev, vdev)
63
64/* Helper API to obtain the parent of the virtio device */
65static inline struct device *mic_dev(struct mic_vdev *mvdev)
66{
67 return mvdev->vdev.dev.parent;
68}
69
70/* This gets the device's feature bits. */
71static u32 mic_get_features(struct virtio_device *vdev)
72{
73 unsigned int i, bits;
74 u32 features = 0;
75 struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
76 u8 __iomem *in_features = mic_vq_features(desc);
77 int feature_len = ioread8(&desc->feature_len);
78
79 bits = min_t(unsigned, feature_len,
80 sizeof(vdev->features)) * 8;
81 for (i = 0; i < bits; i++)
82 if (ioread8(&in_features[i / 8]) & (BIT(i % 8)))
83 features |= BIT(i);
84
85 return features;
86}
87
88static void mic_finalize_features(struct virtio_device *vdev)
89{
90 unsigned int i, bits;
91 struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
92 u8 feature_len = ioread8(&desc->feature_len);
93 /* Second half of bitmap is features we accept. */
94 u8 __iomem *out_features =
95 mic_vq_features(desc) + feature_len;
96
97 /* Give virtio_ring a chance to accept features. */
98 vring_transport_features(vdev);
99
100 memset_io(out_features, 0, feature_len);
101 bits = min_t(unsigned, feature_len,
102 sizeof(vdev->features)) * 8;
103 for (i = 0; i < bits; i++) {
104 if (test_bit(i, vdev->features))
105 iowrite8(ioread8(&out_features[i / 8]) | (1 << (i % 8)),
106 &out_features[i / 8]);
107 }
108}
109
110/*
111 * Reading and writing elements in config space
112 */
113static void mic_get(struct virtio_device *vdev, unsigned int offset,
114 void *buf, unsigned len)
115{
116 struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
117
118 if (offset + len > ioread8(&desc->config_len))
119 return;
120 memcpy_fromio(buf, mic_vq_configspace(desc) + offset, len);
121}
122
123static void mic_set(struct virtio_device *vdev, unsigned int offset,
124 const void *buf, unsigned len)
125{
126 struct mic_device_desc __iomem *desc = to_micvdev(vdev)->desc;
127
128 if (offset + len > ioread8(&desc->config_len))
129 return;
130 memcpy_toio(mic_vq_configspace(desc) + offset, buf, len);
131}
132
133/*
134 * The operations to get and set the status word just access the status
135 * field of the device descriptor. set_status also interrupts the host
136 * to tell about status changes.
137 */
138static u8 mic_get_status(struct virtio_device *vdev)
139{
140 return ioread8(&to_micvdev(vdev)->desc->status);
141}
142
143static void mic_set_status(struct virtio_device *vdev, u8 status)
144{
145 struct mic_vdev *mvdev = to_micvdev(vdev);
146 if (!status)
147 return;
148 iowrite8(status, &mvdev->desc->status);
149 mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
150}
151
152/* Inform host on a virtio device reset and wait for ack from host */
153static void mic_reset_inform_host(struct virtio_device *vdev)
154{
155 struct mic_vdev *mvdev = to_micvdev(vdev);
156 struct mic_device_ctrl __iomem *dc = mvdev->dc;
157 int retry = 100, i;
158
159 iowrite8(0, &dc->host_ack);
160 iowrite8(1, &dc->vdev_reset);
161 mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
162
163 /* Wait till host completes all card accesses and acks the reset */
164 for (i = retry; i--;) {
165 if (ioread8(&dc->host_ack))
166 break;
167 msleep(100);
168 };
169
170 dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
171
172 /* Reset status to 0 in case we timed out */
173 iowrite8(0, &mvdev->desc->status);
174}
175
176static void mic_reset(struct virtio_device *vdev)
177{
178 struct mic_vdev *mvdev = to_micvdev(vdev);
179
180 dev_dbg(mic_dev(mvdev), "%s: virtio id %d\n",
181 __func__, vdev->id.device);
182
183 mic_reset_inform_host(vdev);
184 complete_all(&mvdev->reset_done);
185}
186
187/*
188 * The virtio_ring code calls this API when it wants to notify the Host.
189 */
190static void mic_notify(struct virtqueue *vq)
191{
192 struct mic_vdev *mvdev = vq->priv;
193
194 mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
195}
196
197static void mic_del_vq(struct virtqueue *vq, int n)
198{
199 struct mic_vdev *mvdev = to_micvdev(vq->vdev);
200 struct vring *vr = (struct vring *) (vq + 1);
201
202 free_pages((unsigned long) vr->used,
203 get_order(mvdev->used_size[n]));
204 vring_del_virtqueue(vq);
205 mic_card_unmap(mvdev->mdev, mvdev->vr[n]);
206 mvdev->vr[n] = NULL;
207}
208
209static void mic_del_vqs(struct virtio_device *vdev)
210{
211 struct mic_vdev *mvdev = to_micvdev(vdev);
212 struct virtqueue *vq, *n;
213 int idx = 0;
214
215 dev_dbg(mic_dev(mvdev), "%s\n", __func__);
216
217 list_for_each_entry_safe(vq, n, &vdev->vqs, list)
218 mic_del_vq(vq, idx++);
219}
220
221/*
222 * This routine will assign vring's allocated in host/io memory. Code in
223 * virtio_ring.c however continues to access this io memory as if it were local
224 * memory without io accessors.
225 */
226static struct virtqueue *mic_find_vq(struct virtio_device *vdev,
227 unsigned index,
228 void (*callback)(struct virtqueue *vq),
229 const char *name)
230{
231 struct mic_vdev *mvdev = to_micvdev(vdev);
232 struct mic_vqconfig __iomem *vqconfig;
233 struct mic_vqconfig config;
234 struct virtqueue *vq;
235 void __iomem *va;
236 struct _mic_vring_info __iomem *info;
237 void *used;
238 int vr_size, _vr_size, err, magic;
239 struct vring *vr;
240 u8 type = ioread8(&mvdev->desc->type);
241
242 if (index >= ioread8(&mvdev->desc->num_vq))
243 return ERR_PTR(-ENOENT);
244
245 if (!name)
246 return ERR_PTR(-ENOENT);
247
248 /* First assign the vring's allocated in host memory */
249 vqconfig = mic_vq_config(mvdev->desc) + index;
250 memcpy_fromio(&config, vqconfig, sizeof(config));
251 _vr_size = vring_size(config.num, MIC_VIRTIO_RING_ALIGN);
252 vr_size = PAGE_ALIGN(_vr_size + sizeof(struct _mic_vring_info));
253 va = mic_card_map(mvdev->mdev, config.address, vr_size);
254 if (!va)
255 return ERR_PTR(-ENOMEM);
256 mvdev->vr[index] = va;
257 memset_io(va, 0x0, _vr_size);
258 vq = vring_new_virtqueue(index,
259 config.num, MIC_VIRTIO_RING_ALIGN, vdev,
260 false,
261 va, mic_notify, callback, name);
262 if (!vq) {
263 err = -ENOMEM;
264 goto unmap;
265 }
266 info = va + _vr_size;
267 magic = ioread32(&info->magic);
268
269 if (WARN(magic != MIC_MAGIC + type + index, "magic mismatch")) {
270 err = -EIO;
271 goto unmap;
272 }
273
274 /* Allocate and reassign used ring now */
275 mvdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
276 sizeof(struct vring_used_elem) * config.num);
277 used = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO,
278 get_order(mvdev->used_size[index]));
279 if (!used) {
280 err = -ENOMEM;
281 dev_err(mic_dev(mvdev), "%s %d err %d\n",
282 __func__, __LINE__, err);
283 goto del_vq;
284 }
285 iowrite64(virt_to_phys(used), &vqconfig->used_address);
286
287 /*
288 * To reassign the used ring here we are directly accessing
289 * struct vring_virtqueue which is a private data structure
290 * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
291 * vring_new_virtqueue() would ensure that
292 * (&vq->vring == (struct vring *) (&vq->vq + 1));
293 */
294 vr = (struct vring *) (vq + 1);
295 vr->used = used;
296
297 vq->priv = mvdev;
298 return vq;
299del_vq:
300 vring_del_virtqueue(vq);
301unmap:
302 mic_card_unmap(mvdev->mdev, mvdev->vr[index]);
303 return ERR_PTR(err);
304}
305
306static int mic_find_vqs(struct virtio_device *vdev, unsigned nvqs,
307 struct virtqueue *vqs[],
308 vq_callback_t *callbacks[],
309 const char *names[])
310{
311 struct mic_vdev *mvdev = to_micvdev(vdev);
312 struct mic_device_ctrl __iomem *dc = mvdev->dc;
313 int i, err, retry = 100;
314
315 /* We must have this many virtqueues. */
316 if (nvqs > ioread8(&mvdev->desc->num_vq))
317 return -ENOENT;
318
319 for (i = 0; i < nvqs; ++i) {
320 dev_dbg(mic_dev(mvdev), "%s: %d: %s\n",
321 __func__, i, names[i]);
322 vqs[i] = mic_find_vq(vdev, i, callbacks[i], names[i]);
323 if (IS_ERR(vqs[i])) {
324 err = PTR_ERR(vqs[i]);
325 goto error;
326 }
327 }
328
329 iowrite8(1, &dc->used_address_updated);
330 /*
331 * Send an interrupt to the host to inform it that used
332 * rings have been re-assigned.
333 */
334 mic_send_intr(mvdev->mdev, mvdev->c2h_vdev_db);
335 for (i = retry; i--;) {
336 if (!ioread8(&dc->used_address_updated))
337 break;
338 msleep(100);
339 };
340
341 dev_dbg(mic_dev(mvdev), "%s: retry: %d\n", __func__, retry);
342 if (!retry) {
343 err = -ENODEV;
344 goto error;
345 }
346
347 return 0;
348error:
349 mic_del_vqs(vdev);
350 return err;
351}
352
353/*
354 * The config ops structure as defined by virtio config
355 */
356static struct virtio_config_ops mic_vq_config_ops = {
357 .get_features = mic_get_features,
358 .finalize_features = mic_finalize_features,
359 .get = mic_get,
360 .set = mic_set,
361 .get_status = mic_get_status,
362 .set_status = mic_set_status,
363 .reset = mic_reset,
364 .find_vqs = mic_find_vqs,
365 .del_vqs = mic_del_vqs,
366};
367
368static irqreturn_t
369mic_virtio_intr_handler(int irq, void *data)
370{
371 struct mic_vdev *mvdev = data;
372 struct virtqueue *vq;
373
374 mic_ack_interrupt(mvdev->mdev);
375 list_for_each_entry(vq, &mvdev->vdev.vqs, list)
376 vring_interrupt(0, vq);
377
378 return IRQ_HANDLED;
379}
380
381static void mic_virtio_release_dev(struct device *_d)
382{
383 /*
384 * No need for a release method similar to virtio PCI.
385 * Provide an empty one to avoid getting a warning from core.
386 */
387}
388
389/*
390 * adds a new device and register it with virtio
391 * appropriate drivers are loaded by the device model
392 */
393static int mic_add_device(struct mic_device_desc __iomem *d,
394 unsigned int offset, struct mic_driver *mdrv)
395{
396 struct mic_vdev *mvdev;
397 int ret;
398 int virtio_db;
399 u8 type = ioread8(&d->type);
400
401 mvdev = kzalloc(sizeof(*mvdev), GFP_KERNEL);
402 if (!mvdev) {
403 dev_err(mdrv->dev, "Cannot allocate mic dev %u type %u\n",
404 offset, type);
405 return -ENOMEM;
406 }
407
408 mvdev->mdev = &mdrv->mdev;
409 mvdev->vdev.dev.parent = mdrv->dev;
410 mvdev->vdev.dev.release = mic_virtio_release_dev;
411 mvdev->vdev.id.device = type;
412 mvdev->vdev.config = &mic_vq_config_ops;
413 mvdev->desc = d;
414 mvdev->dc = (void __iomem *)d + mic_aligned_desc_size(d);
415 init_completion(&mvdev->reset_done);
416
417 virtio_db = mic_next_card_db();
418 mvdev->virtio_cookie = mic_request_card_irq(mic_virtio_intr_handler,
419 "virtio intr", mvdev, virtio_db);
420 if (IS_ERR(mvdev->virtio_cookie)) {
421 ret = PTR_ERR(mvdev->virtio_cookie);
422 goto kfree;
423 }
424 iowrite8((u8)virtio_db, &mvdev->dc->h2c_vdev_db);
425 mvdev->c2h_vdev_db = ioread8(&mvdev->dc->c2h_vdev_db);
426
427 ret = register_virtio_device(&mvdev->vdev);
428 if (ret) {
429 dev_err(mic_dev(mvdev),
430 "Failed to register mic device %u type %u\n",
431 offset, type);
432 goto free_irq;
433 }
434 iowrite64((u64)mvdev, &mvdev->dc->vdev);
435 dev_dbg(mic_dev(mvdev), "%s: registered mic device %u type %u mvdev %p\n",
436 __func__, offset, type, mvdev);
437
438 return 0;
439
440free_irq:
441 mic_free_card_irq(mvdev->virtio_cookie, mvdev);
442kfree:
443 kfree(mvdev);
444 return ret;
445}
446
447/*
448 * match for a mic device with a specific desc pointer
449 */
450static int mic_match_desc(struct device *dev, void *data)
451{
452 struct virtio_device *vdev = dev_to_virtio(dev);
453 struct mic_vdev *mvdev = to_micvdev(vdev);
454
455 return mvdev->desc == (void __iomem *)data;
456}
457
458static void mic_handle_config_change(struct mic_device_desc __iomem *d,
459 unsigned int offset, struct mic_driver *mdrv)
460{
461 struct mic_device_ctrl __iomem *dc
462 = (void __iomem *)d + mic_aligned_desc_size(d);
463 struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
464 struct virtio_driver *drv;
465
466 if (ioread8(&dc->config_change) != MIC_VIRTIO_PARAM_CONFIG_CHANGED)
467 return;
468
469 dev_dbg(mdrv->dev, "%s %d\n", __func__, __LINE__);
470 drv = container_of(mvdev->vdev.dev.driver,
471 struct virtio_driver, driver);
472 if (drv->config_changed)
473 drv->config_changed(&mvdev->vdev);
474 iowrite8(1, &dc->guest_ack);
475}
476
477/*
478 * removes a virtio device if a hot remove event has been
479 * requested by the host.
480 */
481static int mic_remove_device(struct mic_device_desc __iomem *d,
482 unsigned int offset, struct mic_driver *mdrv)
483{
484 struct mic_device_ctrl __iomem *dc
485 = (void __iomem *)d + mic_aligned_desc_size(d);
486 struct mic_vdev *mvdev = (struct mic_vdev *)ioread64(&dc->vdev);
487 u8 status;
488 int ret = -1;
489
490 if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
491 dev_dbg(mdrv->dev,
492 "%s %d config_change %d type %d mvdev %p\n",
493 __func__, __LINE__,
494 ioread8(&dc->config_change), ioread8(&d->type), mvdev);
495
496 status = ioread8(&d->status);
497 INIT_COMPLETION(mvdev->reset_done);
498 unregister_virtio_device(&mvdev->vdev);
499 mic_free_card_irq(mvdev->virtio_cookie, mvdev);
500 if (status & VIRTIO_CONFIG_S_DRIVER_OK)
501 wait_for_completion(&mvdev->reset_done);
502 kfree(mvdev);
503 iowrite8(1, &dc->guest_ack);
504 dev_dbg(mdrv->dev, "%s %d guest_ack %d\n",
505 __func__, __LINE__, ioread8(&dc->guest_ack));
506 ret = 0;
507 }
508
509 return ret;
510}
511
512#define REMOVE_DEVICES true
513
514static void mic_scan_devices(struct mic_driver *mdrv, bool remove)
515{
516 s8 type;
517 unsigned int i;
518 struct mic_device_desc __iomem *d;
519 struct mic_device_ctrl __iomem *dc;
520 struct device *dev;
521 int ret;
522
523 for (i = mic_aligned_size(struct mic_bootparam);
524 i < MIC_DP_SIZE; i += mic_total_desc_size(d)) {
525 d = mdrv->dp + i;
526 dc = (void __iomem *)d + mic_aligned_desc_size(d);
527 /*
528 * This read barrier is paired with the corresponding write
529 * barrier on the host which is inserted before adding or
530 * removing a virtio device descriptor, by updating the type.
531 */
532 rmb();
533 type = ioread8(&d->type);
534
535 /* end of list */
536 if (type == 0)
537 break;
538
539 if (type == -1)
540 continue;
541
542 /* device already exists */
543 dev = device_find_child(mdrv->dev, d, mic_match_desc);
544 if (dev) {
545 if (remove)
546 iowrite8(MIC_VIRTIO_PARAM_DEV_REMOVE,
547 &dc->config_change);
548 put_device(dev);
549 mic_handle_config_change(d, i, mdrv);
550 ret = mic_remove_device(d, i, mdrv);
551 if (!ret && !remove)
552 iowrite8(-1, &d->type);
553 if (remove) {
554 iowrite8(0, &dc->config_change);
555 iowrite8(0, &dc->guest_ack);
556 }
557 continue;
558 }
559
560 /* new device */
561 dev_dbg(mdrv->dev, "%s %d Adding new virtio device %p\n",
562 __func__, __LINE__, d);
563 if (!remove)
564 mic_add_device(d, i, mdrv);
565 }
566}
567
568/*
569 * mic_hotplug_device tries to find changes in the device page.
570 */
571static void mic_hotplug_devices(struct work_struct *work)
572{
573 struct mic_driver *mdrv = container_of(work,
574 struct mic_driver, hotplug_work);
575
576 mic_scan_devices(mdrv, !REMOVE_DEVICES);
577}
578
579/*
580 * Interrupt handler for hot plug/config changes etc.
581 */
582static irqreturn_t
583mic_extint_handler(int irq, void *data)
584{
585 struct mic_driver *mdrv = (struct mic_driver *)data;
586
587 dev_dbg(mdrv->dev, "%s %d hotplug work\n",
588 __func__, __LINE__);
589 mic_ack_interrupt(&mdrv->mdev);
590 schedule_work(&mdrv->hotplug_work);
591 return IRQ_HANDLED;
592}
593
594/*
595 * Init function for virtio
596 */
597int mic_devices_init(struct mic_driver *mdrv)
598{
599 int rc;
600 struct mic_bootparam __iomem *bootparam;
601 int config_db;
602
603 INIT_WORK(&mdrv->hotplug_work, mic_hotplug_devices);
604 mic_scan_devices(mdrv, !REMOVE_DEVICES);
605
606 config_db = mic_next_card_db();
607 virtio_config_cookie = mic_request_card_irq(mic_extint_handler,
608 "virtio_config_intr", mdrv, config_db);
609 if (IS_ERR(virtio_config_cookie)) {
610 rc = PTR_ERR(virtio_config_cookie);
611 goto exit;
612 }
613
614 bootparam = mdrv->dp;
615 iowrite8(config_db, &bootparam->h2c_config_db);
616 return 0;
617exit:
618 return rc;
619}
620
621/*
622 * Uninit function for virtio
623 */
624void mic_devices_uninit(struct mic_driver *mdrv)
625{
626 struct mic_bootparam __iomem *bootparam = mdrv->dp;
627 iowrite8(-1, &bootparam->h2c_config_db);
628 mic_free_card_irq(virtio_config_cookie, mdrv);
629 flush_work(&mdrv->hotplug_work);
630 mic_scan_devices(mdrv, REMOVE_DEVICES);
631}
diff --git a/drivers/misc/mic/card/mic_virtio.h b/drivers/misc/mic/card/mic_virtio.h
new file mode 100644
index 000000000000..2c5c22c93ba8
--- /dev/null
+++ b/drivers/misc/mic/card/mic_virtio.h
@@ -0,0 +1,77 @@
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 * Disclaimer: The codes contained in these modules may be specific to
19 * the Intel Software Development Platform codenamed: Knights Ferry, and
20 * the Intel product codenamed: Knights Corner, and are not backward
21 * compatible with other Intel products. Additionally, Intel will NOT
22 * support the codes or instruction set in future products.
23 *
24 * Intel MIC Card driver.
25 *
26 */
27#ifndef __MIC_CARD_VIRTIO_H
28#define __MIC_CARD_VIRTIO_H
29
30#include <linux/mic_common.h>
31#include "mic_device.h"
32
33/*
34 * 64 bit I/O access
35 */
36#ifndef ioread64
37#define ioread64 readq
38#endif
39#ifndef iowrite64
40#define iowrite64 writeq
41#endif
42
43static inline unsigned mic_desc_size(struct mic_device_desc __iomem *desc)
44{
45 return mic_aligned_size(*desc)
46 + ioread8(&desc->num_vq) * mic_aligned_size(struct mic_vqconfig)
47 + ioread8(&desc->feature_len) * 2
48 + ioread8(&desc->config_len);
49}
50
51static inline struct mic_vqconfig __iomem *
52mic_vq_config(struct mic_device_desc __iomem *desc)
53{
54 return (struct mic_vqconfig __iomem *)(desc + 1);
55}
56
57static inline __u8 __iomem *
58mic_vq_features(struct mic_device_desc __iomem *desc)
59{
60 return (__u8 __iomem *)(mic_vq_config(desc) + ioread8(&desc->num_vq));
61}
62
63static inline __u8 __iomem *
64mic_vq_configspace(struct mic_device_desc __iomem *desc)
65{
66 return mic_vq_features(desc) + ioread8(&desc->feature_len) * 2;
67}
68static inline unsigned mic_total_desc_size(struct mic_device_desc __iomem *desc)
69{
70 return mic_aligned_desc_size(desc) +
71 mic_aligned_size(struct mic_device_ctrl);
72}
73
74int mic_devices_init(struct mic_driver *mdrv);
75void mic_devices_uninit(struct mic_driver *mdrv);
76
77#endif