[PATCH v6 net-next] net: hyperv: Add attributes to show TX indirection table

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



An imbalanced TX indirection table causes netvsc to have low
performance. This table is created and managed during runtime. To help
better diagnose performance issues caused by imbalanced tables, add
device attributes to show the content of TX indirection tables.

Signed-off-by: Chi Song <chisong@xxxxxxxxxxxxx>
---
v4: use a separated group to organize tx_indirection better, change 
 location of attributes init/exit to netvsc_drv_init/exit
v5: update variable orders
v6: update names to be more precise, remove useless assignment

Thank you all for comments, learned a lot.

 drivers/net/hyperv/netvsc_drv.c | 48 +++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 6267f706e8ee..f6ad13ed320f 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -2370,6 +2370,50 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
 	return NOTIFY_OK;
 }
 
+static struct device_attribute dev_attr_tx_indirection_attrs[VRSS_SEND_TAB_SIZE];
+static struct attribute *tx_indirection_attrs[VRSS_SEND_TAB_SIZE + 1];
+
+const struct attribute_group tx_indirection_group = {
+	.name = "tx_indirection",
+	.attrs = tx_indirection_attrs,
+};
+
+static ssize_t tx_indirection_show(struct device *dev,
+				   struct device_attribute *dev_attr, char *buf)
+{
+	int index = dev_attr - dev_attr_tx_indirection_attrs;
+	struct net_device *ndev = to_net_dev(dev);
+	struct net_device_context *ndc = netdev_priv(ndev);
+
+	return sprintf(buf, "%u\n", ndc->tx_table[index]);
+}
+
+static void netvsc_attrs_init(void)
+{
+	char buffer[4];
+	int i;
+
+	for (i = 0; i < VRSS_SEND_TAB_SIZE; i++) {
+		sprintf(buffer, "%02u", i);
+		dev_attr_tx_indirection_attrs[i].attr.name =
+			kstrdup(buffer, GFP_KERNEL);
+		dev_attr_tx_indirection_attrs[i].attr.mode = 0444;
+		sysfs_attr_init(&dev_attr_tx_indirection_attrs[i].attr);
+
+		dev_attr_tx_indirection_attrs[i].show = tx_indirection_show;
+		tx_indirection_attrs[i] =
+			&dev_attr_tx_indirection_attrs[i].attr;
+	}
+}
+
+static void netvsc_attrs_exit(void)
+{
+	int i;
+
+	for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
+		kfree(dev_attr_tx_indirection_attrs[i].attr.name);
+}
+
 static int netvsc_probe(struct hv_device *dev,
 			const struct hv_vmbus_device_id *dev_id)
 {
@@ -2410,6 +2454,7 @@ static int netvsc_probe(struct hv_device *dev,
 
 	net->netdev_ops = &device_ops;
 	net->ethtool_ops = &ethtool_ops;
+	net->sysfs_groups[0] = &tx_indirection_group;
 	SET_NETDEV_DEV(net, &dev->device);
 
 	/* We always need headroom for rndis header */
@@ -2665,6 +2710,7 @@ static void __exit netvsc_drv_exit(void)
 {
 	unregister_netdevice_notifier(&netvsc_netdev_notifier);
 	vmbus_driver_unregister(&netvsc_drv);
+	netvsc_attrs_exit();
 }
 
 static int __init netvsc_drv_init(void)
@@ -2678,6 +2724,8 @@ static int __init netvsc_drv_init(void)
 	}
 	netvsc_ring_bytes = ring_size * PAGE_SIZE;
 
+	netvsc_attrs_init();
+
 	ret = vmbus_driver_register(&netvsc_drv);
 	if (ret)
 		return ret;
-- 
2.25.1




[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux