Skip to content

Commit

Permalink
Intel MIC Host Driver Changes for Virtio Devices.
Browse files Browse the repository at this point in the history
This patch introduces the host "Virtio over PCIe" interface for
Intel MIC. It allows creating user space backends on the host and instantiating
virtio devices for them on the Intel MIC card. It uses the existing VRINGH
infrastructure in the kernel to access virtio rings from the host. A character
device per MIC is exposed with IOCTL, mmap and poll callbacks. This allows the
user space backend to:
(a) add/remove a virtio device via a device page.
(b) map (R/O) virtio rings and device page to user space.
(c) poll for availability of data.
(d) copy a descriptor or entire descriptor chain to/from the card.
(e) modify virtio configuration.
(f) handle virtio device reset.
The buffers are copied over using CPU copies for this initial patch
and host initiated MIC DMA support is planned for future patches.
The avail and desc virtio rings are in host memory and the used ring
is in card memory to maximize writes across PCIe for performance.

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>
  • Loading branch information
Ashutosh Dixit authored and Greg Kroah-Hartman committed Sep 26, 2013
1 parent aa27bad commit f69bcbf
Show file tree
Hide file tree
Showing 14 changed files with 1,517 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/misc/mic/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ comment "Intel MIC Host Driver"
config INTEL_MIC_HOST
tristate "Intel MIC Host Driver"
depends on 64BIT && PCI
select VHOST_RING
default N
help
This enables Host Driver support for the Intel Many Integrated
Expand Down
7 changes: 7 additions & 0 deletions drivers/misc/mic/common/mic_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,11 @@ struct mic_mw {
#define MIC_DPLO_SPAD 14
#define MIC_DPHI_SPAD 15

/*
* These values are supposed to be in the config_change field of the
* device page when the host sends a config change interrupt to the card.
*/
#define MIC_VIRTIO_PARAM_DEV_REMOVE 0x1
#define MIC_VIRTIO_PARAM_CONFIG_CHANGED 0x2

#endif
2 changes: 2 additions & 0 deletions drivers/misc/mic/host/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ mic_host-objs += mic_smpt.o
mic_host-objs += mic_intr.o
mic_host-objs += mic_boot.o
mic_host-objs += mic_debugfs.o
mic_host-objs += mic_fops.o
mic_host-objs += mic_virtio.o
3 changes: 2 additions & 1 deletion drivers/misc/mic/host/mic_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
*/
#include <linux/delay.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>

#include <linux/mic_common.h>
#include "../common/mic_device.h"
#include "mic_device.h"
#include "mic_smpt.h"
#include "mic_virtio.h"

/**
* mic_reset - Reset the MIC device.
Expand Down Expand Up @@ -117,6 +117,7 @@ void mic_stop(struct mic_device *mdev, bool force)
{
mutex_lock(&mdev->mic_mutex);
if (MIC_OFFLINE != mdev->state || force) {
mic_virtio_reset_devices(mdev);
mic_bootparam_init(mdev);
mic_reset(mdev);
if (MIC_RESET_FAILED == mdev->state)
Expand Down
140 changes: 140 additions & 0 deletions drivers/misc/mic/host/mic_debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "../common/mic_device.h"
#include "mic_device.h"
#include "mic_smpt.h"
#include "mic_virtio.h"

/* Debugfs parent dir */
static struct dentry *mic_dbg;
Expand Down Expand Up @@ -193,7 +194,13 @@ static const struct file_operations post_code_ops = {
static int mic_dp_show(struct seq_file *s, void *pos)
{
struct mic_device *mdev = s->private;
struct mic_device_desc *d;
struct mic_device_ctrl *dc;
struct mic_vqconfig *vqconfig;
__u32 *features;
__u8 *config;
struct mic_bootparam *bootparam = mdev->dp;
int i, j;

seq_printf(s, "Bootparam: magic 0x%x\n",
bootparam->magic);
Expand All @@ -208,6 +215,53 @@ static int mic_dp_show(struct seq_file *s, void *pos)
seq_printf(s, "Bootparam: shutdown_card %d\n",
bootparam->shutdown_card);

for (i = sizeof(*bootparam); i < MIC_DP_SIZE;
i += mic_total_desc_size(d)) {
d = mdev->dp + i;
dc = (void *)d + mic_aligned_desc_size(d);

/* end of list */
if (d->type == 0)
break;

if (d->type == -1)
continue;

seq_printf(s, "Type %d ", d->type);
seq_printf(s, "Num VQ %d ", d->num_vq);
seq_printf(s, "Feature Len %d\n", d->feature_len);
seq_printf(s, "Config Len %d ", d->config_len);
seq_printf(s, "Shutdown Status %d\n", d->status);

for (j = 0; j < d->num_vq; j++) {
vqconfig = mic_vq_config(d) + j;
seq_printf(s, "vqconfig[%d]: ", j);
seq_printf(s, "address 0x%llx ", vqconfig->address);
seq_printf(s, "num %d ", vqconfig->num);
seq_printf(s, "used address 0x%llx\n",
vqconfig->used_address);
}

features = (__u32 *) mic_vq_features(d);
seq_printf(s, "Features: Host 0x%x ", features[0]);
seq_printf(s, "Guest 0x%x\n", features[1]);

config = mic_vq_configspace(d);
for (j = 0; j < d->config_len; j++)
seq_printf(s, "config[%d]=%d\n", j, config[j]);

seq_puts(s, "Device control:\n");
seq_printf(s, "Config Change %d ", dc->config_change);
seq_printf(s, "Vdev reset %d\n", dc->vdev_reset);
seq_printf(s, "Guest Ack %d ", dc->guest_ack);
seq_printf(s, "Host ack %d\n", dc->host_ack);
seq_printf(s, "Used address updated %d ",
dc->used_address_updated);
seq_printf(s, "Vdev 0x%llx\n", dc->vdev);
seq_printf(s, "c2h doorbell %d ", dc->c2h_vdev_db);
seq_printf(s, "h2c doorbell %d\n", dc->h2c_vdev_db);
}

return 0;
}

Expand All @@ -229,6 +283,89 @@ static const struct file_operations dp_ops = {
.release = mic_dp_debug_release
};

static int mic_vdev_info_show(struct seq_file *s, void *unused)
{
struct mic_device *mdev = s->private;
struct list_head *pos, *tmp;
struct mic_vdev *mvdev;
int i, j;

mutex_lock(&mdev->mic_mutex);
list_for_each_safe(pos, tmp, &mdev->vdev_list) {
mvdev = list_entry(pos, struct mic_vdev, list);
seq_printf(s, "VDEV type %d state %s in %ld out %ld\n",
mvdev->virtio_id,
mic_vdevup(mvdev) ? "UP" : "DOWN",
mvdev->in_bytes,
mvdev->out_bytes);
for (i = 0; i < MIC_MAX_VRINGS; i++) {
struct vring_desc *desc;
struct vring_avail *avail;
struct vring_used *used;
struct mic_vringh *mvr = &mvdev->mvr[i];
struct vringh *vrh = &mvr->vrh;
int num = vrh->vring.num;
if (!num)
continue;
desc = vrh->vring.desc;
seq_printf(s, "vring i %d avail_idx %d",
i, mvr->vring.info->avail_idx & (num - 1));
seq_printf(s, " vring i %d avail_idx %d\n",
i, mvr->vring.info->avail_idx);
seq_printf(s, "vrh i %d weak_barriers %d",
i, vrh->weak_barriers);
seq_printf(s, " last_avail_idx %d last_used_idx %d",
vrh->last_avail_idx, vrh->last_used_idx);
seq_printf(s, " completed %d\n", vrh->completed);
for (j = 0; j < num; j++) {
seq_printf(s, "desc[%d] addr 0x%llx len %d",
j, desc->addr, desc->len);
seq_printf(s, " flags 0x%x next %d\n",
desc->flags,
desc->next);
desc++;
}
avail = vrh->vring.avail;
seq_printf(s, "avail flags 0x%x idx %d\n",
avail->flags, avail->idx & (num - 1));
seq_printf(s, "avail flags 0x%x idx %d\n",
avail->flags, avail->idx);
for (j = 0; j < num; j++)
seq_printf(s, "avail ring[%d] %d\n",
j, avail->ring[j]);
used = vrh->vring.used;
seq_printf(s, "used flags 0x%x idx %d\n",
used->flags, used->idx & (num - 1));
seq_printf(s, "used flags 0x%x idx %d\n",
used->flags, used->idx);
for (j = 0; j < num; j++)
seq_printf(s, "used ring[%d] id %d len %d\n",
j, used->ring[j].id, used->ring[j].len);
}
}
mutex_unlock(&mdev->mic_mutex);

return 0;
}

static int mic_vdev_info_debug_open(struct inode *inode, struct file *file)
{
return single_open(file, mic_vdev_info_show, inode->i_private);
}

static int mic_vdev_info_debug_release(struct inode *inode, struct file *file)
{
return single_release(inode, file);
}

static const struct file_operations vdev_info_ops = {
.owner = THIS_MODULE,
.open = mic_vdev_info_debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = mic_vdev_info_debug_release
};

static int mic_msi_irq_info_show(struct seq_file *s, void *pos)
{
struct mic_device *mdev = s->private;
Expand Down Expand Up @@ -321,6 +458,9 @@ void mic_create_debug_dir(struct mic_device *mdev)
debugfs_create_file("dp", 0444, mdev->dbg_dir,
mdev, &dp_ops);

debugfs_create_file("vdev_info", 0444, mdev->dbg_dir,
mdev, &vdev_info_ops);

debugfs_create_file("msi_irq_info", 0444, mdev->dbg_dir,
mdev, &msi_irq_info_ops);
}
Expand Down
5 changes: 5 additions & 0 deletions drivers/misc/mic/host/mic_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#ifndef _MIC_DEVICE_H_
#define _MIC_DEVICE_H_

#include <linux/cdev.h>
#include <linux/idr.h>

#include "mic_intr.h"
Expand Down Expand Up @@ -80,6 +81,8 @@ enum mic_stepping {
* @dp_dma_addr: virtio device page DMA address.
* @shutdown_db: shutdown doorbell.
* @shutdown_cookie: shutdown cookie.
* @cdev: Character device for MIC.
* @vdev_list: list of virtio devices.
*/
struct mic_device {
struct mic_mw mmio;
Expand Down Expand Up @@ -113,6 +116,8 @@ struct mic_device {
dma_addr_t dp_dma_addr;
int shutdown_db;
struct mic_irq *shutdown_cookie;
struct cdev cdev;
struct list_head vdev_list;
};

/**
Expand Down
Loading

0 comments on commit f69bcbf

Please sign in to comment.