From: Yonglong Liu liuyonglong@huawei.com
driver inclusion category: feature bugzilla: NA CVE: NA
----------------------------
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@huawei.com Reviewed-by: li yongxin liyongxin1@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- drivers/net/ethernet/hisilicon/hns3/Makefile | 3 +- drivers/net/ethernet/hisilicon/hns3/hnae3.h | 8 + .../hns3_extension/hns3pf/hclge_main_it.c | 33 +++++ .../hns3/hns3_extension/hns3pf/hclge_sysfs.c | 140 ++++++++++++++++++ .../hns3/hns3_extension/hns3pf/hclge_sysfs.h | 14 ++ .../hisilicon/hns3/hns3pf/hclge_main.c | 17 +++ .../hisilicon/hns3/hns3pf/hclge_main.h | 5 + 7 files changed, 219 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 e1c520226ddd..5bec09bb6e9e 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 3c56cbc9afa6..7b3938054e5f 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,11 @@ struct hnae3_handle {
/* Network interface message level enabled bits */ u32 msg_enable; + +#ifdef CONFIG_HNS3_TEST + /* for sysfs */ + struct kobject *kobj; +#endif };
#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 01f0e19f1e50..59e287848ee3 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 000000000000..86e60938013c --- /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 000000000000..8eb33357c577 --- /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 b40cf43ba8c0..7b6d7c157747 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 08d17ba61960..f803a9d895c0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -970,6 +970,11 @@ 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 */ + +#ifdef CONFIG_HNS3_TEST + /* for sysfs */ + struct kobject kobj; +#endif };
int hclge_set_vport_promisc_mode(struct hclge_vport *vport, bool en_uc_pmc,