driver inclusion
category: feature
bugzilla: NA
CVE: NA
DTS:SR20210201768145
----------------------------
This patch adds support for setting/getting pf max tx rate via sysfs:
echo <rate Mbit/s> > /sys/class/net/<eth name>/kunpeng/pf/max_tx_rate
cat /sys/class/net/<eth name>/kunpeng/pf/max_tx_rate
Signed-off-by: Yonglong Liu <liuyonglong(a)huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/Makefile | 3 +-
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 6 +
.../hns3/hns3_extension/hns3pf/hclge_main_it.c | 33 +++++
.../hns3/hns3_extension/hns3pf/hclge_sysfs.c | 140 +++++++++++++++++++++
.../hns3/hns3_extension/hns3pf/hclge_sysfs.h | 14 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 17 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 3 +
7 files changed, 215 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c
create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h
diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile
index bd607c0..5efa685 100644
--- a/drivers/net/ethernet/hisilicon/hns3/Makefile
+++ b/drivers/net/ethernet/hisilicon/hns3/Makefile
@@ -38,7 +38,8 @@ HCLGE_OBJ = hns3pf/hclge_main.o \
hns3pf/hclge_err.o
-HCLGE_OBJ_IT_MAIN = hns3_extension/hns3pf/hclge_main_it.o
+HCLGE_OBJ_IT_MAIN = hns3_extension/hns3pf/hclge_main_it.o \
+ hns3_extension/hns3pf/hclge_sysfs.o
obj-$(CONFIG_HNS3_HCLGE) += hclge.o
hclge-objs := $(HCLGE_OBJ) $(HCLGE_OBJ_IT_MAIN)
hclge-$(CONFIG_HNS3_DCB) += hns3pf/hclge_dcb.o
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 3c56cbc..ac8a7c1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -578,6 +578,9 @@ struct hnae3_ae_ops {
int (*ecc_handle)(struct hnae3_ae_dev *ae_dev);
int (*priv_ops)(struct hnae3_handle *handle, int opcode,
void *data, int length);
+ void (*ext_init)(struct hnae3_handle *handle);
+ void (*ext_uninit)(struct hnae3_handle *handle);
+ void (*ext_reset_done)(struct hnae3_handle *handle);
#endif
};
@@ -713,6 +716,9 @@ struct hnae3_handle {
/* Network interface message level enabled bits */
u32 msg_enable;
+
+ /* for sysfs */
+ struct kobject *kobj;
};
#define hnae3_set_field(origin, mask, shift, val) \
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.c b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.c
index 01f0e19..59e2878 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.c
@@ -18,6 +18,9 @@
#include "hclge_main.h"
#include "hnae3.h"
#include "hclge_main_it.h"
+#ifdef CONFIG_HNS3_TEST
+#include "hclge_sysfs.h"
+#endif
#ifdef CONFIG_IT_VALIDATION
#define HCLGE_RESET_MAX_FAIL_CNT 1
@@ -174,8 +177,38 @@ bool hclge_reset_done_it(struct hnae3_handle *handle, bool done)
return done;
}
+#ifdef CONFIG_HNS3_TEST
+void hclge_ext_init(struct hnae3_handle *handle)
+{
+ hclge_sysfs_init(handle);
+}
+
+void hclge_ext_uninit(struct hnae3_handle *handle)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+
+ hclge_reset_pf_rate(hdev);
+ hclge_sysfs_uninit(handle);
+}
+
+void hclge_ext_reset_done(struct hnae3_handle *handle)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+
+ hclge_resume_pf_rate(hdev);
+}
+#endif
+
int hclge_init_it(void)
{
+#ifdef CONFIG_HNS3_TEST
+ hclge_ops.ext_init = hclge_ext_init;
+ hclge_ops.ext_uninit = hclge_ext_uninit;
+ hclge_ops.ext_reset_done = hclge_ext_reset_done;
+#endif
+
hclge_ops.reset_event = hclge_reset_event_it;
hclge_ops.reset_done = hclge_reset_done_it;
hclge_ops.handle_imp_error = hclge_handle_imp_error_it;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c
new file mode 100644
index 00000000..86e6093
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2018-2021 Hisilicon Limited. */
+
+#include <linux/device.h>
+#include "hnae3.h"
+#include "hclge_main.h"
+#include "hclge_tm.h"
+#include "hclge_sysfs.h"
+
+void hclge_reset_pf_rate(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = &hdev->vport[0];
+ int ret;
+
+ /* zero means max rate, if max_tx_rate is zero, just return */
+ if (!vport->vf_info.max_tx_rate)
+ return;
+
+ vport->vf_info.max_tx_rate = 0;
+
+ ret = hclge_tm_qs_shaper_cfg(vport, vport->vf_info.max_tx_rate);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "failed to reset pf tx rate to default, ret = %d.\n",
+ ret);
+}
+
+int hclge_resume_pf_rate(struct hclge_dev *hdev)
+{
+ struct hclge_vport *vport = &hdev->vport[0];
+ int ret;
+
+ /* zero means max rate, after reset, firmware already set it to
+ * max rate, so just continue.
+ */
+ if (!vport->vf_info.max_tx_rate)
+ return 0;
+
+ ret = hclge_tm_qs_shaper_cfg(vport, vport->vf_info.max_tx_rate);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "failed to resume pf tx rate:%u, ret = %d.\n",
+ vport->vf_info.max_tx_rate, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static ssize_t hclge_max_tx_rate_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ struct hclge_vport *vport =
+ container_of(kobj, struct hclge_vport, kobj);
+
+ return sprintf(buf, "%d Mbit/s (0 means no limit)\n",
+ vport->vf_info.max_tx_rate);
+}
+
+static ssize_t hclge_max_tx_rate_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t size)
+{
+ struct hclge_vport *vport =
+ container_of(kobj, struct hclge_vport, kobj);
+ struct hclge_dev *hdev = vport->back;
+ int max_tx_rate;
+ int ret;
+
+ ret = kstrtoint(buf, 0, &max_tx_rate);
+ if (ret)
+ return -EINVAL;
+
+ if (max_tx_rate < 0 || max_tx_rate > hdev->hw.mac.max_speed) {
+ dev_err(&hdev->pdev->dev,
+ "invalid max_tx_rate:%d [0, %u]\n",
+ max_tx_rate, hdev->hw.mac.max_speed);
+ return -EINVAL;
+ }
+
+ ret = hclge_tm_qs_shaper_cfg(vport, max_tx_rate);
+ if (ret)
+ return ret;
+
+ vport->vf_info.max_tx_rate = max_tx_rate;
+
+ return ret ? (ssize_t)ret : size;
+}
+
+static struct kobj_attribute hclge_attr_max_tx_rate = {
+ .attr = {.name = "max_tx_rate",
+ .mode = 0644 },
+ .show = hclge_max_tx_rate_show,
+ .store = hclge_max_tx_rate_store,
+};
+
+static struct attribute *hclge_sysfs_attrs[] = {
+ &hclge_attr_max_tx_rate.attr,
+ NULL,
+};
+
+static struct kobj_type hclge_sysfs_type = {
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_attrs = hclge_sysfs_attrs,
+};
+
+void hclge_sysfs_init(struct hnae3_handle *handle)
+{
+ struct net_device *netdev = handle->netdev;
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ int ret;
+
+ handle->kobj = kobject_create_and_add("kunpeng", &netdev->dev.kobj);
+ if (!handle->kobj) {
+ netdev_err(netdev, "failed to create kobj, ret = %d\n", ret);
+ return;
+ }
+
+ ret = kobject_init_and_add(&vport->kobj, &hclge_sysfs_type,
+ handle->kobj, "pf");
+ if (ret) {
+ netdev_err(netdev, "failed to init kobj, ret = %d\n", ret);
+ kobject_put(handle->kobj);
+ handle->kobj = NULL;
+ }
+}
+
+void hclge_sysfs_uninit(struct hnae3_handle *handle)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+
+ if (!handle->kobj)
+ return;
+
+ kobject_put(&vport->kobj);
+ kobject_put(handle->kobj);
+ handle->kobj = NULL;
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h
new file mode 100644
index 00000000..8eb3335
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_sysfs.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0+
+ * Copyright (c) 2018-2021 Hisilicon Limited.
+ */
+
+#ifndef __HCLGE_SYSFS_H
+#define __HCLGE_SYSFS_H
+
+void hclge_reset_pf_rate(struct hclge_dev *hdev);
+int hclge_resume_pf_rate(struct hclge_dev *hdev);
+
+void hclge_sysfs_init(struct hnae3_handle *handle);
+void hclge_sysfs_uninit(struct hnae3_handle *handle);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index b40cf43..7b6d7c1 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -9946,6 +9946,11 @@ static int hclge_init_nic_client_instance(struct hnae3_ae_dev *ae_dev,
if (ret)
return ret;
+#ifdef CONFIG_HNS3_TEST
+ if (ae_dev->ops->ext_init)
+ ae_dev->ops->ext_init(&vport->nic);
+#endif
+
set_bit(HCLGE_STATE_NIC_REGISTERED, &hdev->state);
if (test_bit(HCLGE_STATE_RST_HANDLING, &hdev->state) ||
rst_cnt != hdev->rst_stats.reset_cnt) {
@@ -10087,6 +10092,13 @@ static void hclge_uninit_client_instance(struct hnae3_client *client,
struct hclge_vport *vport;
int i;
+#ifdef CONFIG_HNS3_TEST
+ if (ae_dev->ops->ext_uninit) {
+ vport = &hdev->vport[0];
+ ae_dev->ops->ext_uninit(&vport->nic);
+ }
+#endif
+
for (i = 0; i < hdev->num_vmdq_vport + 1; i++) {
vport = &hdev->vport[i];
if (hdev->roce_client) {
@@ -10817,6 +10829,11 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
if (ret)
return ret;
+#ifdef CONFIG_HNS3_TEST
+ if (ae_dev->ops->ext_reset_done)
+ ae_dev->ops->ext_reset_done(&hdev->vport->nic);
+#endif
+
dev_info(&pdev->dev, "Reset done, %s driver initialization finished.\n",
HCLGE_DRIVER_NAME);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 08d17ba..a0d2b4d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -970,6 +970,9 @@ struct hclge_vport {
struct list_head uc_mac_list; /* Store VF unicast table */
struct list_head mc_mac_list; /* Store VF multicast table */
struct list_head vlan_list; /* Store VF vlan table */
+
+ /* for sysfs */
+ struct kobject kobj;
};
int hclge_set_vport_promisc_mode(struct hclge_vport *vport, bool en_uc_pmc,
--
2.7.4