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

Commit 7047f17d authored by K. Y. Srinivasan's avatar K. Y. Srinivasan Committed by Greg Kroah-Hartman
Browse files

Drivers: hv: vmbus: Add vendor and device atttributes



Add vendor and device attributes to VMBUS devices. These will be used
by Hyper-V tools as well user-level RDMA libraries that will use the
vendor/device tuple to discover the RDMA device.

Signed-off-by: default avatarK. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1b807e10
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -27,3 +27,17 @@ Description: The mapping of which primary/sub channels are bound to which
		Virtual Processors.
		Format: <channel's child_relid:the bound cpu's number>
Users:		tools/hv/lsvmbus

What:		/sys/bus/vmbus/devices/vmbus_*/device
Date:		Dec. 2015
KernelVersion:	4.5
Contact:	K. Y. Srinivasan <kys@microsoft.com>
Description:	The 16 bit device ID of the device
Users:		tools/hv/lsvmbus and user level RDMA libraries

What:		/sys/bus/vmbus/devices/vmbus_*/vendor
Date:		Dec. 2015
KernelVersion:	4.5
Contact:	K. Y. Srinivasan <kys@microsoft.com>
Description:	The 16 bit vendor ID of the device
Users:		tools/hv/lsvmbus and user level RDMA libraries
+123 −43
Original line number Diff line number Diff line
@@ -32,8 +32,122 @@

#include "hyperv_vmbus.h"

static void init_vp_index(struct vmbus_channel *channel,
			  const uuid_le *type_guid);
static void init_vp_index(struct vmbus_channel *channel, u16 dev_type);

static const struct vmbus_device vmbus_devs[] = {
	/* IDE */
	{ .dev_type = HV_IDE,
	  HV_IDE_GUID,
	  .perf_device = true,
	},

	/* SCSI */
	{ .dev_type = HV_SCSI,
	  HV_SCSI_GUID,
	  .perf_device = true,
	},

	/* Fibre Channel */
	{ .dev_type = HV_FC,
	  HV_SYNTHFC_GUID,
	  .perf_device = true,
	},

	/* Synthetic NIC */
	{ .dev_type = HV_NIC,
	  HV_NIC_GUID,
	  .perf_device = true,
	},

	/* Network Direct */
	{ .dev_type = HV_ND,
	  HV_ND_GUID,
	  .perf_device = true,
	},

	/* PCIE */
	{ .dev_type = HV_PCIE,
	  HV_PCIE_GUID,
	  .perf_device = true,
	},

	/* Synthetic Frame Buffer */
	{ .dev_type = HV_FB,
	  HV_SYNTHVID_GUID,
	  .perf_device = false,
	},

	/* Synthetic Keyboard */
	{ .dev_type = HV_KBD,
	  HV_KBD_GUID,
	  .perf_device = false,
	},

	/* Synthetic MOUSE */
	{ .dev_type = HV_MOUSE,
	  HV_MOUSE_GUID,
	  .perf_device = false,
	},

	/* KVP */
	{ .dev_type = HV_KVP,
	  HV_KVP_GUID,
	  .perf_device = false,
	},

	/* Time Synch */
	{ .dev_type = HV_TS,
	  HV_TS_GUID,
	  .perf_device = false,
	},

	/* Heartbeat */
	{ .dev_type = HV_HB,
	  HV_HEART_BEAT_GUID,
	  .perf_device = false,
	},

	/* Shutdown */
	{ .dev_type = HV_SHUTDOWN,
	  HV_SHUTDOWN_GUID,
	  .perf_device = false,
	},

	/* File copy */
	{ .dev_type = HV_FCOPY,
	  HV_FCOPY_GUID,
	  .perf_device = false,
	},

	/* Backup */
	{ .dev_type = HV_BACKUP,
	  HV_VSS_GUID,
	  .perf_device = false,
	},

	/* Dynamic Memory */
	{ .dev_type = HV_DM,
	  HV_DM_GUID,
	  .perf_device = false,
	},

	/* Unknown GUID */
	{ .dev_type = HV_UNKOWN,
	  .perf_device = false,
	},
};

static u16 hv_get_dev_type(const uuid_le *guid)
{
	u16 i;

	for (i = HV_IDE; i < HV_UNKOWN; i++) {
		if (!uuid_le_cmp(*guid, vmbus_devs[i].guid))
			return i;
	}
	pr_info("Unknown GUID: %pUl\n", guid);
	return i;
}

/**
 * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message
@@ -251,6 +365,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
	struct vmbus_channel *channel;
	bool fnew = true;
	unsigned long flags;
	u16 dev_type;

	/* Make sure this is a new offer */
	mutex_lock(&vmbus_connection.channel_mutex);
@@ -288,7 +403,9 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
			goto err_free_chan;
	}

	init_vp_index(newchannel, &newchannel->offermsg.offer.if_type);
	dev_type = hv_get_dev_type(&newchannel->offermsg.offer.if_type);

	init_vp_index(newchannel, dev_type);

	if (newchannel->target_cpu != get_cpu()) {
		put_cpu();
@@ -325,6 +442,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
	if (!newchannel->device_obj)
		goto err_deq_chan;

	newchannel->device_obj->device_id = dev_type;
	/*
	 * Add the new device to the bus. This will kick off device-driver
	 * binding which eventually invokes the device driver's AddDevice()
@@ -358,37 +476,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
	free_channel(newchannel);
}

enum {
	IDE = 0,
	SCSI,
	FC,
	NIC,
	ND_NIC,
	PCIE,
	MAX_PERF_CHN,
};

/*
 * This is an array of device_ids (device types) that are performance critical.
 * We attempt to distribute the interrupt load for these devices across
 * all available CPUs.
 */
static const struct hv_vmbus_device_id hp_devs[] = {
	/* IDE */
	{ HV_IDE_GUID, },
	/* Storage - SCSI */
	{ HV_SCSI_GUID, },
	/* Storage - FC */
	{ HV_SYNTHFC_GUID, },
	/* Network */
	{ HV_NIC_GUID, },
	/* NetworkDirect Guest RDMA */
	{ HV_ND_GUID, },
	/* PCI Express Pass Through */
	{ HV_PCIE_GUID, },
};


/*
 * We use this state to statically distribute the channel interrupt load.
 */
@@ -405,22 +492,15 @@ static int next_numa_node_id;
 * For pre-win8 hosts or non-performance critical channels we assign the
 * first CPU in the first NUMA node.
 */
static void init_vp_index(struct vmbus_channel *channel, const uuid_le *type_guid)
static void init_vp_index(struct vmbus_channel *channel, u16 dev_type)
{
	u32 cur_cpu;
	int i;
	bool perf_chn = false;
	bool perf_chn = vmbus_devs[dev_type].perf_device;
	struct vmbus_channel *primary = channel->primary_channel;
	int next_node;
	struct cpumask available_mask;
	struct cpumask *alloced_mask;

	for (i = IDE; i < MAX_PERF_CHN; i++) {
		if (!uuid_le_cmp(*type_guid, hp_devs[i].guid)) {
			perf_chn = true;
			break;
		}
	}
	if ((vmbus_proto_version == VERSION_WS2008) ||
	    (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
		/*
+21 −0
Original line number Diff line number Diff line
@@ -477,6 +477,24 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
}
static DEVICE_ATTR_RO(channel_vp_mapping);

static ssize_t vendor_show(struct device *dev,
			   struct device_attribute *dev_attr,
			   char *buf)
{
	struct hv_device *hv_dev = device_to_hv_device(dev);
	return sprintf(buf, "0x%x\n", hv_dev->vendor_id);
}
static DEVICE_ATTR_RO(vendor);

static ssize_t device_show(struct device *dev,
			   struct device_attribute *dev_attr,
			   char *buf)
{
	struct hv_device *hv_dev = device_to_hv_device(dev);
	return sprintf(buf, "0x%x\n", hv_dev->device_id);
}
static DEVICE_ATTR_RO(device);

/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
static struct attribute *vmbus_attrs[] = {
	&dev_attr_id.attr,
@@ -502,6 +520,8 @@ static struct attribute *vmbus_attrs[] = {
	&dev_attr_in_read_bytes_avail.attr,
	&dev_attr_in_write_bytes_avail.attr,
	&dev_attr_channel_vp_mapping.attr,
	&dev_attr_vendor.attr,
	&dev_attr_device.attr,
	NULL,
};
ATTRIBUTE_GROUPS(vmbus);
@@ -957,6 +977,7 @@ struct hv_device *vmbus_device_create(const uuid_le *type,
	memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le));
	memcpy(&child_device_obj->dev_instance, instance,
	       sizeof(uuid_le));
	child_device_obj->vendor_id = 0x1414; /* MSFT vendor ID */


	return child_device_obj;
+28 −0
Original line number Diff line number Diff line
@@ -633,6 +633,32 @@ enum hv_signal_policy {
	HV_SIGNAL_POLICY_EXPLICIT,
};

enum vmbus_device_type {
	HV_IDE = 0,
	HV_SCSI,
	HV_FC,
	HV_NIC,
	HV_ND,
	HV_PCIE,
	HV_FB,
	HV_KBD,
	HV_MOUSE,
	HV_KVP,
	HV_TS,
	HV_HB,
	HV_SHUTDOWN,
	HV_FCOPY,
	HV_BACKUP,
	HV_DM,
	HV_UNKOWN,
};

struct vmbus_device {
	u16  dev_type;
	uuid_le guid;
	bool perf_device;
};

struct vmbus_channel {
	/* Unique channel id */
	int id;
@@ -959,6 +985,8 @@ struct hv_device {

	/* the device instance id of this device */
	uuid_le dev_instance;
	u16 vendor_id;
	u16 device_id;

	struct device device;