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

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
...@@ -27,3 +27,17 @@ Description: The mapping of which primary/sub channels are bound to which ...@@ -27,3 +27,17 @@ Description: The mapping of which primary/sub channels are bound to which
Virtual Processors. Virtual Processors.
Format: <channel's child_relid:the bound cpu's number> Format: <channel's child_relid:the bound cpu's number>
Users: tools/hv/lsvmbus 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
...@@ -32,8 +32,122 @@ ...@@ -32,8 +32,122 @@
#include "hyperv_vmbus.h" #include "hyperv_vmbus.h"
static void init_vp_index(struct vmbus_channel *channel, static void init_vp_index(struct vmbus_channel *channel, u16 dev_type);
const uuid_le *type_guid);
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 * 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) ...@@ -251,6 +365,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
struct vmbus_channel *channel; struct vmbus_channel *channel;
bool fnew = true; bool fnew = true;
unsigned long flags; unsigned long flags;
u16 dev_type;
/* Make sure this is a new offer */ /* Make sure this is a new offer */
mutex_lock(&vmbus_connection.channel_mutex); mutex_lock(&vmbus_connection.channel_mutex);
...@@ -288,7 +403,9 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) ...@@ -288,7 +403,9 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
goto err_free_chan; 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()) { if (newchannel->target_cpu != get_cpu()) {
put_cpu(); put_cpu();
...@@ -325,6 +442,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) ...@@ -325,6 +442,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
if (!newchannel->device_obj) if (!newchannel->device_obj)
goto err_deq_chan; goto err_deq_chan;
newchannel->device_obj->device_id = dev_type;
/* /*
* Add the new device to the bus. This will kick off device-driver * Add the new device to the bus. This will kick off device-driver
* binding which eventually invokes the device driver's AddDevice() * binding which eventually invokes the device driver's AddDevice()
...@@ -358,37 +476,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) ...@@ -358,37 +476,6 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel)
free_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. * We use this state to statically distribute the channel interrupt load.
*/ */
...@@ -405,22 +492,15 @@ static int next_numa_node_id; ...@@ -405,22 +492,15 @@ static int next_numa_node_id;
* For pre-win8 hosts or non-performance critical channels we assign the * For pre-win8 hosts or non-performance critical channels we assign the
* first CPU in the first NUMA node. * 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; u32 cur_cpu;
int i; bool perf_chn = vmbus_devs[dev_type].perf_device;
bool perf_chn = false;
struct vmbus_channel *primary = channel->primary_channel; struct vmbus_channel *primary = channel->primary_channel;
int next_node; int next_node;
struct cpumask available_mask; struct cpumask available_mask;
struct cpumask *alloced_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) || if ((vmbus_proto_version == VERSION_WS2008) ||
(vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) { (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
/* /*
......
...@@ -477,6 +477,24 @@ static ssize_t channel_vp_mapping_show(struct device *dev, ...@@ -477,6 +477,24 @@ static ssize_t channel_vp_mapping_show(struct device *dev,
} }
static DEVICE_ATTR_RO(channel_vp_mapping); 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> */ /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
static struct attribute *vmbus_attrs[] = { static struct attribute *vmbus_attrs[] = {
&dev_attr_id.attr, &dev_attr_id.attr,
...@@ -502,6 +520,8 @@ static struct attribute *vmbus_attrs[] = { ...@@ -502,6 +520,8 @@ static struct attribute *vmbus_attrs[] = {
&dev_attr_in_read_bytes_avail.attr, &dev_attr_in_read_bytes_avail.attr,
&dev_attr_in_write_bytes_avail.attr, &dev_attr_in_write_bytes_avail.attr,
&dev_attr_channel_vp_mapping.attr, &dev_attr_channel_vp_mapping.attr,
&dev_attr_vendor.attr,
&dev_attr_device.attr,
NULL, NULL,
}; };
ATTRIBUTE_GROUPS(vmbus); ATTRIBUTE_GROUPS(vmbus);
...@@ -957,6 +977,7 @@ struct hv_device *vmbus_device_create(const uuid_le *type, ...@@ -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_type, type, sizeof(uuid_le));
memcpy(&child_device_obj->dev_instance, instance, memcpy(&child_device_obj->dev_instance, instance,
sizeof(uuid_le)); sizeof(uuid_le));
child_device_obj->vendor_id = 0x1414; /* MSFT vendor ID */
return child_device_obj; return child_device_obj;
......
...@@ -633,6 +633,32 @@ enum hv_signal_policy { ...@@ -633,6 +633,32 @@ enum hv_signal_policy {
HV_SIGNAL_POLICY_EXPLICIT, 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 { struct vmbus_channel {
/* Unique channel id */ /* Unique channel id */
int id; int id;
...@@ -959,6 +985,8 @@ struct hv_device { ...@@ -959,6 +985,8 @@ struct hv_device {
/* the device instance id of this device */ /* the device instance id of this device */
uuid_le dev_instance; uuid_le dev_instance;
u16 vendor_id;
u16 device_id;
struct device device; struct device device;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment