413 lines
14 KiB
Diff
413 lines
14 KiB
Diff
From 274e8e310c46db5cf2e04f41960adf1696b5374b Mon Sep 17 00:00:00 2001
|
|
From: Jian Shen <shenjian15@huawei.com>
|
|
Date: Wed, 30 Nov 2022 18:23:33 +0800
|
|
Subject: [PATCH 186/283] net: hns3: add queue bonding mode support for VF
|
|
|
|
driver inclusion
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN3D
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
For device version V3, the hardware supports queue bonding
|
|
mode. VF can not enable queue bond mode unless PF enables it.
|
|
So VF needs to query whether PF support queue bonding mode
|
|
when initializing, and query whether PF enables queue bonding
|
|
mode periodically. For the resource limited, to avoid a VF
|
|
occupy to many FD rule space, only trust VF is allowed to enable
|
|
queue bonding mode.
|
|
|
|
Signed-off-by: Jian Shen <shenjian15@huawei.com>
|
|
Signed-off-by: Jiantao Xiao <xiaojiantao1@h-partners.com>
|
|
Reviewed-by: Yue Haibing <yuehaibing@huawei.com>
|
|
Reviewed-by: Jian Shen <shenjian15@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
---
|
|
.../net/ethernet/hisilicon/hns3/hclge_mbx.h | 6 ++
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 50 ++++++++++++-
|
|
.../hisilicon/hns3/hns3pf/hclge_main.h | 2 +
|
|
.../hisilicon/hns3/hns3pf/hclge_mbx.c | 37 ++++++++++
|
|
.../hisilicon/hns3/hns3vf/hclgevf_main.c | 74 +++++++++++++++++++
|
|
.../hisilicon/hns3/hns3vf/hclgevf_main.h | 8 ++
|
|
.../hisilicon/hns3/hns3vf/hclgevf_mbx.c | 17 +++++
|
|
7 files changed, 193 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
|
|
index 05a1b789c9ab..cb6e3c40471a 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h
|
|
@@ -79,6 +79,12 @@ enum hclge_mbx_tbl_cfg_subcode {
|
|
HCLGE_MBX_VPORT_LIST_CLEAR,
|
|
};
|
|
|
|
+enum hclge_mbx_qb_cfg_subcode {
|
|
+ HCLGE_MBX_QB_CHECK_CAPS = 0, /* query whether support qb */
|
|
+ HCLGE_MBX_QB_ENABLE, /* request pf enable qb */
|
|
+ HCLGE_MBX_QB_GET_STATE /* query whether qb enabled */
|
|
+};
|
|
+
|
|
#define HCLGE_MBX_MAX_MSG_SIZE 14
|
|
#define HCLGE_MBX_MAX_RESP_DATA_SIZE 8U
|
|
#define HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM 4
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
index 5fcae2b54ac7..c6bebf2a9e31 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -4565,6 +4565,7 @@ static int hclge_sync_pf_qb_mode(struct hclge_dev *hdev)
|
|
struct hnae3_handle *handle = &vport->nic;
|
|
bool request_enable = true;
|
|
int ret;
|
|
+ u16 i;
|
|
|
|
if (!test_and_clear_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state))
|
|
return 0;
|
|
@@ -4593,6 +4594,11 @@ static int hclge_sync_pf_qb_mode(struct hclge_dev *hdev)
|
|
clear_bit(HCLGE_STATE_HW_QB_ENABLE, &hdev->state);
|
|
hdev->fd_active_type = HCLGE_FD_RULE_NONE;
|
|
}
|
|
+
|
|
+ for (i = 1; i < hdev->num_alloc_vport; i++) {
|
|
+ vport = &hdev->vport[i];
|
|
+ set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
+ }
|
|
} else {
|
|
set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
}
|
|
@@ -4601,10 +4607,33 @@ static int hclge_sync_pf_qb_mode(struct hclge_dev *hdev)
|
|
return ret;
|
|
}
|
|
|
|
+static int hclge_sync_vf_qb_mode(struct hclge_vport *vport)
|
|
+{
|
|
+ struct hclge_dev *hdev = vport->back;
|
|
+ bool request_enable = false;
|
|
+ int ret;
|
|
+
|
|
+ if (!test_and_clear_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state))
|
|
+ return 0;
|
|
+
|
|
+ if (vport->vf_info.trusted && vport->vf_info.request_qb_en &&
|
|
+ test_bit(HCLGE_STATE_HW_QB_ENABLE, &hdev->state))
|
|
+ request_enable = true;
|
|
+
|
|
+ ret = hclge_set_fd_qb(hdev, vport->vport_id, request_enable);
|
|
+ if (ret)
|
|
+ set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
+ vport->vf_info.qb_en = request_enable ? 1 : 0;
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int hclge_disable_fd_qb_mode(struct hclge_dev *hdev)
|
|
{
|
|
struct hnae3_ae_dev *ae_dev = hdev->ae_dev;
|
|
+ struct hclge_vport *vport;
|
|
int ret;
|
|
+ u16 i;
|
|
|
|
if (!test_bit(HNAE3_DEV_SUPPORT_QB_B, ae_dev->caps) ||
|
|
!test_bit(HCLGE_STATE_HW_QB_ENABLE, &hdev->state))
|
|
@@ -4616,17 +4645,35 @@ static int hclge_disable_fd_qb_mode(struct hclge_dev *hdev)
|
|
|
|
clear_bit(HCLGE_STATE_HW_QB_ENABLE, &hdev->state);
|
|
|
|
+ for (i = 1; i < hdev->num_alloc_vport; i++) {
|
|
+ vport = &hdev->vport[i];
|
|
+ set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
static void hclge_sync_fd_qb_mode(struct hclge_dev *hdev)
|
|
{
|
|
struct hnae3_ae_dev *ae_dev = hdev->ae_dev;
|
|
+ struct hclge_vport *vport;
|
|
+ int ret;
|
|
+ u16 i;
|
|
|
|
if (!test_bit(HNAE3_DEV_SUPPORT_QB_B, ae_dev->caps))
|
|
return;
|
|
|
|
- hclge_sync_pf_qb_mode(hdev);
|
|
+ ret = hclge_sync_pf_qb_mode(hdev);
|
|
+ if (ret)
|
|
+ return;
|
|
+
|
|
+ for (i = 1; i < hdev->num_alloc_vport; i++) {
|
|
+ vport = &hdev->vport[i];
|
|
+
|
|
+ ret = hclge_sync_vf_qb_mode(vport);
|
|
+ if (ret)
|
|
+ return;
|
|
+ }
|
|
}
|
|
|
|
static void hclge_periodic_service_task(struct hclge_dev *hdev)
|
|
@@ -11392,6 +11439,7 @@ static int hclge_set_vf_trust(struct hnae3_handle *handle, int vf, bool enable)
|
|
|
|
vport->vf_info.trusted = new_trusted;
|
|
|
|
+ set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state);
|
|
hclge_task_schedule(hdev, 0);
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
index 65c7b8a534aa..4924aaad757d 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
|
|
@@ -1005,6 +1005,8 @@ struct hclge_vf_info {
|
|
u32 spoofchk;
|
|
u32 max_tx_rate;
|
|
u32 trusted;
|
|
+ u8 request_qb_en;
|
|
+ u8 qb_en;
|
|
u8 request_uc_en;
|
|
u8 request_mc_en;
|
|
u8 request_bc_en;
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
index ec84f81fff92..305f11c854bf 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
|
|
@@ -822,6 +822,36 @@ static void hclge_handle_vf_tbl(struct hclge_vport *vport,
|
|
}
|
|
}
|
|
|
|
+static void hclge_handle_vf_qb(struct hclge_vport *vport,
|
|
+ struct hclge_mbx_vf_to_pf_cmd *mbx_req,
|
|
+ struct hclge_respond_to_vf_msg *resp_msg)
|
|
+{
|
|
+ struct hclge_dev *hdev = vport->back;
|
|
+
|
|
+ if (mbx_req->msg.subcode == HCLGE_MBX_QB_CHECK_CAPS) {
|
|
+ struct hnae3_handle *handle = &hdev->vport[0].nic;
|
|
+
|
|
+ resp_msg->data[0] = test_bit(HNAE3_PFLAG_FD_QB_ENABLE,
|
|
+ &handle->supported_pflags);
|
|
+ resp_msg->len = sizeof(u8);
|
|
+ } else if (mbx_req->msg.subcode == HCLGE_MBX_QB_ENABLE) {
|
|
+ vport->vf_info.request_qb_en = mbx_req->msg.data[0];
|
|
+ set_bit(HCLGE_VPORT_STATE_QB_CHANGE, &vport->state);
|
|
+ } else if (mbx_req->msg.subcode == HCLGE_MBX_QB_GET_STATE) {
|
|
+ u16 msg_data = vport->vf_info.qb_en;
|
|
+ int ret;
|
|
+
|
|
+ ret = hclge_send_mbx_msg(vport, (u8 *)&msg_data,
|
|
+ sizeof(msg_data),
|
|
+ HCLGE_MBX_PUSH_QB_STATE,
|
|
+ vport->vport_id);
|
|
+ if (ret)
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to inform qb state to vport %u, ret = %d\n",
|
|
+ vport->vport_id, ret);
|
|
+ }
|
|
+}
|
|
+
|
|
static int
|
|
hclge_mbx_map_ring_to_vector_handler(struct hclge_mbx_ops_param *param)
|
|
{
|
|
@@ -1031,6 +1061,12 @@ static int hclge_mbx_handle_vf_tbl_handler(struct hclge_mbx_ops_param *param)
|
|
return 0;
|
|
}
|
|
|
|
+static int hclge_mbx_handle_vf_qb_handler(struct hclge_mbx_ops_param *param)
|
|
+{
|
|
+ hclge_handle_vf_qb(param->vport, param->req, param->resp_msg);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = {
|
|
[HCLGE_MBX_RESET] = hclge_mbx_reset_handler,
|
|
[HCLGE_MBX_SET_UNICAST] = hclge_mbx_set_unicast_handler,
|
|
@@ -1055,6 +1091,7 @@ static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = {
|
|
[HCLGE_MBX_VF_UNINIT] = hclge_mbx_vf_uninit_handler,
|
|
[HCLGE_MBX_HANDLE_VF_TBL] = hclge_mbx_handle_vf_tbl_handler,
|
|
[HCLGE_MBX_GET_RING_VECTOR_MAP] = hclge_mbx_get_ring_vector_map_handler,
|
|
+ [HCLGE_MBX_SET_QB] = hclge_mbx_handle_vf_qb_handler,
|
|
[HCLGE_MBX_GET_VF_FLR_STATUS] = hclge_mbx_get_vf_flr_status_handler,
|
|
[HCLGE_MBX_PUSH_LINK_STATUS] = hclge_mbx_push_link_status_handler,
|
|
[HCLGE_MBX_NCSI_ERROR] = hclge_mbx_ncsi_error_handler,
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
index d03d6c22b051..8bd2d8019425 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
|
|
@@ -472,6 +472,74 @@ static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
|
|
return 0;
|
|
}
|
|
|
|
+static void hclgevf_update_fd_qb_state(struct hclgevf_dev *hdev)
|
|
+{
|
|
+ struct hnae3_handle *handle = &hdev->nic;
|
|
+ struct hclge_vf_to_pf_msg send_msg;
|
|
+ int ret;
|
|
+
|
|
+ if (!hdev->qb_cfg.pf_support_qb ||
|
|
+ !test_bit(HNAE3_PFLAG_FD_QB_ENABLE, &handle->priv_flags))
|
|
+ return;
|
|
+
|
|
+ hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_QB,
|
|
+ HCLGE_MBX_QB_GET_STATE);
|
|
+ ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
|
|
+ if (ret)
|
|
+ dev_err(&hdev->pdev->dev, "failed to get qb state, ret = %d",
|
|
+ ret);
|
|
+}
|
|
+
|
|
+static void hclgevf_get_pf_qb_caps(struct hclgevf_dev *hdev)
|
|
+{
|
|
+ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
|
|
+ struct hclge_vf_to_pf_msg send_msg;
|
|
+ u8 resp_msg;
|
|
+ int ret;
|
|
+
|
|
+ if (!test_bit(HNAE3_DEV_SUPPORT_QB_B, ae_dev->caps))
|
|
+ return;
|
|
+
|
|
+ hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_QB,
|
|
+ HCLGE_MBX_QB_CHECK_CAPS);
|
|
+ ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg,
|
|
+ sizeof(resp_msg));
|
|
+ if (ret) {
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to get qb caps from PF, ret = %d", ret);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ hdev->qb_cfg.pf_support_qb = resp_msg > 0;
|
|
+}
|
|
+
|
|
+static void hclgevf_set_fd_qb(struct hnae3_handle *handle)
|
|
+{
|
|
+#define HCLGEVF_QB_MBX_STATE_OFFSET 0
|
|
+
|
|
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
|
+ struct hclge_vf_to_pf_msg send_msg;
|
|
+ u8 resp_msg;
|
|
+ int ret;
|
|
+
|
|
+ hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_QB,
|
|
+ HCLGE_MBX_QB_ENABLE);
|
|
+ send_msg.data[HCLGEVF_QB_MBX_STATE_OFFSET] =
|
|
+ test_bit(HNAE3_PFLAG_FD_QB_ENABLE, &handle->priv_flags) ? 1 : 0;
|
|
+ ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg,
|
|
+ sizeof(resp_msg));
|
|
+ if (ret)
|
|
+ dev_err(&hdev->pdev->dev, "failed to set qb state, ret = %d",
|
|
+ ret);
|
|
+}
|
|
+
|
|
+static bool hclgevf_query_fd_qb_state(struct hnae3_handle *handle)
|
|
+{
|
|
+ struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
|
|
+
|
|
+ return hdev->qb_cfg.hw_qb_en;
|
|
+}
|
|
+
|
|
static void hclgevf_request_link_info(struct hclgevf_dev *hdev)
|
|
{
|
|
struct hclge_vf_to_pf_msg send_msg;
|
|
@@ -2328,6 +2396,8 @@ static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
|
|
|
|
hclgevf_sync_promisc_mode(hdev);
|
|
|
|
+ hclgevf_update_fd_qb_state(hdev);
|
|
+
|
|
hdev->last_serv_processed = jiffies;
|
|
|
|
out:
|
|
@@ -3328,6 +3398,8 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
|
|
goto err_config;
|
|
}
|
|
|
|
+ hclgevf_get_pf_qb_caps(hdev);
|
|
+
|
|
set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state);
|
|
|
|
hdev->last_reset_time = jiffies;
|
|
@@ -3769,6 +3841,8 @@ static const struct hnae3_ae_ops hclgevf_ops = {
|
|
.get_link_mode = hclgevf_get_link_mode,
|
|
.set_promisc_mode = hclgevf_set_promisc_mode,
|
|
.request_update_promisc_mode = hclgevf_request_update_promisc_mode,
|
|
+ .request_flush_qb_config = hclgevf_set_fd_qb,
|
|
+ .query_fd_qb_state = hclgevf_query_fd_qb_state,
|
|
};
|
|
|
|
static struct hnae3_ae_algo ae_algovf = {
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
index 97e9834c6de5..a8366fbf394a 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
|
|
@@ -272,6 +272,11 @@ struct hclgevf_mac_table_cfg {
|
|
struct list_head mc_mac_list;
|
|
};
|
|
|
|
+struct hclgevf_qb_cfg {
|
|
+ bool pf_support_qb;
|
|
+ bool hw_qb_en;
|
|
+};
|
|
+
|
|
struct hclgevf_dev {
|
|
struct pci_dev *pdev;
|
|
struct hnae3_ae_dev *ae_dev;
|
|
@@ -338,6 +343,9 @@ struct hclgevf_dev {
|
|
u32 flag;
|
|
unsigned long serv_processed_cnt;
|
|
unsigned long last_serv_processed;
|
|
+
|
|
+ struct hclgevf_qb_cfg qb_cfg;
|
|
+ struct devlink *devlink;
|
|
};
|
|
|
|
static inline bool hclgevf_is_reset_pending(struct hclgevf_dev *hdev)
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
index 5e43289d714a..ccd45b3c532d 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
|
|
@@ -281,6 +281,7 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev)
|
|
case HCLGE_MBX_LINK_STAT_MODE:
|
|
case HCLGE_MBX_PUSH_VLAN_INFO:
|
|
case HCLGE_MBX_PUSH_PROMISC_INFO:
|
|
+ case HCLGE_MBX_PUSH_QB_STATE:
|
|
hclgevf_handle_mbx_msg(hdev, req);
|
|
break;
|
|
default:
|
|
@@ -306,6 +307,19 @@ static void hclgevf_parse_promisc_info(struct hclgevf_dev *hdev,
|
|
"Promisc mode is closed by host for being untrusted.\n");
|
|
}
|
|
|
|
+static void hclgevf_parse_qb_info(struct hclgevf_dev *hdev, u16 qb_state)
|
|
+{
|
|
+#define HCLGEVF_HW_QB_ON 1
|
|
+#define HCLGEVF_HW_QB_OFF 0
|
|
+
|
|
+ if (qb_state > HCLGEVF_HW_QB_ON) {
|
|
+ dev_warn(&hdev->pdev->dev, "Invalid state, ignored.\n");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ hdev->qb_cfg.hw_qb_en = qb_state > HCLGEVF_HW_QB_OFF;
|
|
+}
|
|
+
|
|
void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
|
|
{
|
|
enum hnae3_reset_type reset_type;
|
|
@@ -375,6 +389,9 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
|
|
case HCLGE_MBX_PUSH_PROMISC_INFO:
|
|
hclgevf_parse_promisc_info(hdev, msg_q[1]);
|
|
break;
|
|
+ case HCLGE_MBX_PUSH_QB_STATE:
|
|
+ hclgevf_parse_qb_info(hdev, msg_q[1]);
|
|
+ break;
|
|
default:
|
|
dev_err(&hdev->pdev->dev,
|
|
"fetched unsupported(%u) message from arq\n",
|
|
--
|
|
2.34.1
|
|
|