Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8810df37 authored by Sudeep Dutt's avatar Sudeep Dutt Committed by Greg Kroah-Hartman
Browse files

misc: mic: Enable VOP debugfs and driver build



This patch moves the virtio specific debugfs hooks previously in
mic_debugfs.c in the MIC host driver into the VOP driver. The
Kconfig/Makefile is also updated to allow building the VOP driver.

Reviewed-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Signed-off-by: default avatarSudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent c1becd28
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -124,3 +124,23 @@ config MIC_COSM
	  More information about the Intel MIC family as well as the Linux
	  OS and tools for MIC to use with this driver are available from
	  <http://software.intel.com/en-us/mic-developer>.

comment "VOP Driver"

config VOP
	tristate "VOP Driver"
	depends on 64BIT && PCI && X86 && VOP_BUS
	select VHOST_RING
	help
	  This enables VOP (Virtio over PCIe) Driver support for the Intel
	  Many Integrated Core (MIC) family of PCIe form factor coprocessor
	  devices. The VOP driver allows virtio drivers, e.g. net, console
	  and block drivers, on the card connect to user space virtio
	  devices on the host.

	  If you are building a host kernel with an Intel MIC device then
	  say M (recommended) or Y, else say N. If unsure say N.

	  More information about the Intel MIC family as well as the Linux
	  OS and tools for MIC to use with this driver are available from
	  <http://software.intel.com/en-us/mic-developer>.
+1 −0
Original line number Diff line number Diff line
@@ -8,3 +8,4 @@ obj-y += bus/
obj-$(CONFIG_SCIF) += scif/
obj-$(CONFIG_MIC_COSM) += cosm/
obj-$(CONFIG_MIC_COSM) += cosm_client/
obj-$(CONFIG_VOP) += vop/
+9 −0
Original line number Diff line number Diff line
#
# Makefile - Intel MIC Linux driver.
# Copyright(c) 2016, Intel Corporation.
#
obj-m := vop.o

vop-objs += vop_main.o
vop-objs += vop_debugfs.o
vop-objs += vop_vringh.o
+232 −0
Original line number Diff line number Diff line
/*
 * Intel MIC Platform Software Stack (MPSS)
 *
 * Copyright(c) 2016 Intel Corporation.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * The full GNU General Public License is included in this distribution in
 * the file called "COPYING".
 *
 * Intel Virtio Over PCIe (VOP) driver.
 *
 */
#include <linux/debugfs.h>
#include <linux/seq_file.h>

#include "vop_main.h"

static int vop_dp_show(struct seq_file *s, void *pos)
{
	struct mic_device_desc *d;
	struct mic_device_ctrl *dc;
	struct mic_vqconfig *vqconfig;
	__u32 *features;
	__u8 *config;
	struct vop_info *vi = s->private;
	struct vop_device *vpdev = vi->vpdev;
	struct mic_bootparam *bootparam = vpdev->hw_ops->get_dp(vpdev);
	int j, k;

	seq_printf(s, "Bootparam: magic 0x%x\n",
		   bootparam->magic);
	seq_printf(s, "Bootparam: h2c_config_db %d\n",
		   bootparam->h2c_config_db);
	seq_printf(s, "Bootparam: node_id %d\n",
		   bootparam->node_id);
	seq_printf(s, "Bootparam: c2h_scif_db %d\n",
		   bootparam->c2h_scif_db);
	seq_printf(s, "Bootparam: h2c_scif_db %d\n",
		   bootparam->h2c_scif_db);
	seq_printf(s, "Bootparam: scif_host_dma_addr 0x%llx\n",
		   bootparam->scif_host_dma_addr);
	seq_printf(s, "Bootparam: scif_card_dma_addr 0x%llx\n",
		   bootparam->scif_card_dma_addr);

	for (j = sizeof(*bootparam);
		j < MIC_DP_SIZE; j += mic_total_desc_size(d)) {
		d = (void *)bootparam + j;
		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 (k = 0; k < d->num_vq; k++) {
			vqconfig = mic_vq_config(d) + k;
			seq_printf(s, "vqconfig[%d]: ", k);
			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 (k = 0; k < d->config_len; k++)
			seq_printf(s, "config[%d]=%d\n", k, config[k]);

		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);
	}
	schedule_work(&vi->hotplug_work);
	return 0;
}

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

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

static const struct file_operations dp_ops = {
	.owner   = THIS_MODULE,
	.open    = vop_dp_debug_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = vop_dp_debug_release
};

static int vop_vdev_info_show(struct seq_file *s, void *unused)
{
	struct vop_info *vi = s->private;
	struct list_head *pos, *tmp;
	struct vop_vdev *vdev;
	int i, j;

	mutex_lock(&vi->vop_mutex);
	list_for_each_safe(pos, tmp, &vi->vdev_list) {
		vdev = list_entry(pos, struct vop_vdev, list);
		seq_printf(s, "VDEV type %d state %s in %ld out %ld in_dma %ld out_dma %ld\n",
			   vdev->virtio_id,
			   vop_vdevup(vdev) ? "UP" : "DOWN",
			   vdev->in_bytes,
			   vdev->out_bytes,
			   vdev->in_bytes_dma,
			   vdev->out_bytes_dma);
		for (i = 0; i < MIC_MAX_VRINGS; i++) {
			struct vring_desc *desc;
			struct vring_avail *avail;
			struct vring_used *used;
			struct vop_vringh *vvr = &vdev->vvr[i];
			struct vringh *vrh = &vvr->vrh;
			int num = vrh->vring.num;

			if (!num)
				continue;
			desc = vrh->vring.desc;
			seq_printf(s, "vring i %d avail_idx %d",
				   i, vvr->vring.info->avail_idx & (num - 1));
			seq_printf(s, " vring i %d avail_idx %d\n",
				   i, vvr->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",
				   vringh16_to_cpu(vrh, avail->flags),
				   vringh16_to_cpu(vrh,
						   avail->idx) & (num - 1));
			seq_printf(s, "avail flags 0x%x idx %d\n",
				   vringh16_to_cpu(vrh, avail->flags),
				   vringh16_to_cpu(vrh, 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",
				   vringh16_to_cpu(vrh, used->flags),
				   vringh16_to_cpu(vrh, used->idx) & (num - 1));
			seq_printf(s, "used flags 0x%x idx %d\n",
				   vringh16_to_cpu(vrh, used->flags),
				   vringh16_to_cpu(vrh, used->idx));
			for (j = 0; j < num; j++)
				seq_printf(s, "used ring[%d] id %d len %d\n",
					   j, vringh32_to_cpu(vrh,
							      used->ring[j].id),
					   vringh32_to_cpu(vrh,
							   used->ring[j].len));
		}
	}
	mutex_unlock(&vi->vop_mutex);

	return 0;
}

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

static int vop_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    = vop_vdev_info_debug_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = vop_vdev_info_debug_release
};

void vop_init_debugfs(struct vop_info *vi)
{
	char name[16];

	snprintf(name, sizeof(name), "%s%d", KBUILD_MODNAME, vi->vpdev->dnode);
	vi->dbg = debugfs_create_dir(name, NULL);
	if (!vi->dbg) {
		pr_err("can't create debugfs dir vop\n");
		return;
	}
	debugfs_create_file("dp", 0444, vi->dbg, vi, &dp_ops);
	debugfs_create_file("vdev_info", 0444, vi->dbg, vi, &vdev_info_ops);
}

void vop_exit_debugfs(struct vop_info *vi)
{
	debugfs_remove_recursive(vi->dbg);
}