From 66962d2f2ca31c150b28b43e99654f6c85889357 Mon Sep 17 00:00:00 2001 From: Tian Jiang Date: Thu, 9 Mar 2023 10:59:36 +0800 Subject: [PATCH 191/283] net: hns3: add support customized exception handling interfaces. driver inclusion category: feature bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN3D CVE: NA ---------------------------------------------------------------------- Establish a framework to support customization requirement. Provides interfaces to register special processing functions. When the system is reset due to an abnormal interrupt, the registered handler is called first. Signed-off-by: Tian Jiang Signed-off-by: shaojijie Signed-off-by: Jiantao Xiao Signed-off-by: Xiaodong Li Conflicts: drivers/net/ethernet/hisilicon/hns3/Makefile drivers/net/ethernet/hisilicon/hns3/hnae3.h drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h --- drivers/net/ethernet/hisilicon/hns3/Makefile | 3 + drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 + .../net/ethernet/hisilicon/hns3/hnae3_ext.h | 32 ++++ .../net/ethernet/hisilicon/hns3/hns3_enet.c | 5 + .../net/ethernet/hisilicon/hns3/hns3_ext.c | 76 ++++++++ .../net/ethernet/hisilicon/hns3/hns3_ext.h | 13 ++ .../hns3_extension/hns3pf/hclge_main_it.c | 22 +-- .../hns3_extension/hns3pf/hclge_main_it.h | 32 ---- .../hisilicon/hns3/hns3pf/hclge_ext.c | 178 ++++++++++++++++++ .../hisilicon/hns3/hns3pf/hclge_ext.h | 43 +++++ .../hisilicon/hns3/hns3pf/hclge_main.c | 45 ++--- .../hisilicon/hns3/hns3pf/hclge_main.h | 5 +- .../hisilicon/hns3/hns3pf/hclge_mbx.c | 2 +- 13 files changed, 382 insertions(+), 76 deletions(-) create mode 100644 drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_ext.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3_ext.h create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c create mode 100644 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h diff --git a/drivers/net/ethernet/hisilicon/hns3/Makefile b/drivers/net/ethernet/hisilicon/hns3/Makefile index 70bf49da5591..d0f56781b558 100644 --- a/drivers/net/ethernet/hisilicon/hns3/Makefile +++ b/drivers/net/ethernet/hisilicon/hns3/Makefile @@ -26,6 +26,7 @@ HNS3_OBJS = hns3_enet.o \ HNS3_OBJS_IT = hns3_extension/hns3_enet_it.o obj-$(CONFIG_HNS3_ENET) += hns3.o hns3-objs = $(HNS3_OBJS) $(HNS3_OBJS_IT) +hns3-objs += hns3_ext.o hns3-$(CONFIG_HNS3_DCB) += hns3_dcbnl.o @@ -44,6 +45,8 @@ 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-objs += hns3pf/hclge_ext.o + hclge-$(CONFIG_HNS3_DCB) += hns3pf/hclge_dcb.o #### compile hclgevf.ko obj-$(CONFIG_HNS3_HCLGEVF) += hclgevf.o diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index d15038e8bcb5..970ef08ce9cc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -787,6 +787,8 @@ struct hnae3_ae_ops { struct ethtool_wolinfo *wol); int (*set_wol)(struct hnae3_handle *handle, struct ethtool_wolinfo *wol); + int (*priv_ops)(struct hnae3_handle *handle, int opcode, + void *data, size_t length); /* Notice! If the function is not for test, the definition must before * CONFIG_HNS3_TEST! Because RoCE will use this head file, and it won't * set CONFIG_HNS3_TEST, that may cause RoCE calling the wrong function. diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h b/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h new file mode 100644 index 000000000000..0b1fa53dfb41 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3_ext.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +// Copyright (c) 2023 Hisilicon Limited. + +#ifndef __HNAE3_EXT_H +#define __HNAE3_EXT_H + +enum hnae3_event_type_custom { + HNAE3_VF_RESET_CUSTOM, + HNAE3_VF_FUNC_RESET_CUSTOM, + HNAE3_VF_PF_FUNC_RESET_CUSTOM, + HNAE3_VF_FULL_RESET_CUSTOM, + HNAE3_FLR_RESET_CUSTOM, + HNAE3_FUNC_RESET_CUSTOM, + HNAE3_GLOBAL_RESET_CUSTOM, + HNAE3_IMP_RESET_CUSTOM, + HNAE3_UNKNOWN_RESET_CUSTOM, + HNAE3_NONE_RESET_CUSTOM, + HNAE3_PORT_FAULT, + HNAE3_RESET_DONE_CUSTOM, + HNAE3_FUNC_RESET_FAIL_CUSTOM, + HNAE3_GLOBAL_RESET_FAIL_CUSTOM, + HNAE3_IMP_RESET_FAIL_CUSTOM, + HNAE3_PPU_POISON_CUSTOM, + HNAE3_IMP_RD_POISON_CUSTOM, + HNAE3_INVALID_EVENT_CUSTOM +}; + +enum hnae3_ext_opcode { + HNAE3_EXT_OPC_RESET, + HNAE3_EXT_OPC_EVENT_CALLBACK, +}; +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 2ca9e369c4bc..72cc7f16aa7e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -23,6 +23,7 @@ #include "kcompat.h" #include "hnae3.h" +#include "hnae3_ext.h" #include "hns3_enet.h" /* All hns3 tracepoints are defined by the include below, which * must be included exactly once across the whole kernel with @@ -5526,6 +5527,10 @@ static void hns3_process_hw_error(struct hnae3_handle *handle, if (hns3_hw_err[i].type == type) { dev_err(&handle->pdev->dev, "Detected %s!\n", hns3_hw_err[i].msg); + if (handle->ae_algo->ops->priv_ops) + handle->ae_algo->ops->priv_ops(handle, + HNAE3_EXT_OPC_EVENT_CALLBACK, &type, + sizeof(type)); break; } } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c new file mode 100644 index 000000000000..34aadd10feb8 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hns3_ext.h" + +int nic_netdev_match_check(struct net_device *ndev) +{ +#define HNS3_DRIVER_NAME_LEN 5 + + struct ethtool_drvinfo drv_info; + struct hnae3_handle *h; + + if (!ndev || !ndev->ethtool_ops || + !ndev->ethtool_ops->get_drvinfo) + return -EINVAL; + + ndev->ethtool_ops->get_drvinfo(ndev, &drv_info); + + if (strncmp(drv_info.driver, "hns3", HNS3_DRIVER_NAME_LEN)) + return -EINVAL; + + h = hns3_get_handle(ndev); + if (h->flags & HNAE3_SUPPORT_VF) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(nic_netdev_match_check); + +static int nic_invoke_pri_ops(struct net_device *ndev, int opcode, + void *data, size_t length) + +{ + struct hnae3_handle *h; + int ret; + + if ((!data && length) || (data && !length)) { + netdev_err(ndev, "failed to check data and length"); + return -EINVAL; + } + + if (nic_netdev_match_check(ndev)) + return -ENODEV; + + h = hns3_get_handle(ndev); + if (!h->ae_algo->ops->priv_ops) + return -EOPNOTSUPP; + + ret = h->ae_algo->ops->priv_ops(h, opcode, data, length); + if (ret) + netdev_err(ndev, + "failed to invoke pri ops, opcode = %#x, ret = %d\n", + opcode, ret); + + return ret; +} + +void nic_chip_recover_handler(struct net_device *ndev, + enum hnae3_event_type_custom event_t) +{ + dev_info(&ndev->dev, "reset type is %d!!\n", event_t); + + if (event_t == HNAE3_PPU_POISON_CUSTOM) + event_t = HNAE3_FUNC_RESET_CUSTOM; + + if (event_t != HNAE3_FUNC_RESET_CUSTOM && + event_t != HNAE3_GLOBAL_RESET_CUSTOM && + event_t != HNAE3_IMP_RESET_CUSTOM) { + dev_err(&ndev->dev, "reset type err!!\n"); + return; + } + + nic_invoke_pri_ops(ndev, HNAE3_EXT_OPC_RESET, + &event_t, sizeof(event_t)); +} +EXPORT_SYMBOL(nic_chip_recover_handler); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h new file mode 100644 index 000000000000..ce92a666db17 --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ext.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2023 Hisilicon Limited. */ + +#ifndef __HNS3_EXT_H +#define __HNS3_EXT_H +#include +#include "hns3_enet.h" +#include "hnae3_ext.h" + +int nic_netdev_match_check(struct net_device *netdev); +void nic_chip_recover_handler(struct net_device *ndev, + enum hnae3_event_type_custom event_t); +#endif 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 0118b9577a66..37b121632ddc 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,7 @@ #include "hclge_main.h" #include "hnae3.h" #include "hclge_main_it.h" +#include "hclge_ext.h" #ifdef CONFIG_HNS3_TEST #include "hclge_sysfs.h" #endif @@ -27,27 +28,6 @@ static nic_event_fn_t nic_event_call; -int nic_register_event(nic_event_fn_t event_call) -{ - if (!event_call) { - pr_err("register event handle is null.\n"); - return -EINVAL; - } - - nic_event_call = event_call; - - pr_info("netdev register success.\n"); - return 0; -} -EXPORT_SYMBOL(nic_register_event); - -int nic_unregister_event(void) -{ - nic_event_call = NULL; - return 0; -} -EXPORT_SYMBOL(nic_unregister_event); - static void nic_call_event(struct net_device *netdev, enum hnae3_event_type_custom event_t) { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.h b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.h index 343e036412d4..290c221f1807 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_extension/hns3pf/hclge_main_it.h @@ -7,25 +7,6 @@ extern struct hnae3_ae_algo ae_algo; extern struct hnae3_ae_ops hclge_ops; -enum hnae3_event_type_custom { - HNAE3_VF_RESET_CUSTOM, - HNAE3_VF_FUNC_RESET_CUSTOM, - HNAE3_VF_PF_FUNC_RESET_CUSTOM, - HNAE3_VF_FULL_RESET_CUSTOM, - HNAE3_FLR_RESET_CUSTOM, - HNAE3_FUNC_RESET_CUSTOM, - HNAE3_GLOBAL_RESET_CUSTOM, - HNAE3_IMP_RESET_CUSTOM, - HNAE3_UNKNOWN_RESET_CUSTOM, - HNAE3_NONE_RESET_CUSTOM, - HNAE3_PORT_FAULT, - HNAE3_RESET_DONE_CUSTOM, - HNAE3_FUNC_RESET_FAIL_CUSTOM, - HNAE3_GLOBAL_RESET_FAIL_CUSTOM, - HNAE3_IMP_RESET_FAIL_CUSTOM, - HNAE3_PPU_POISON_CUSTOM, - HNAE3_IMP_RD_POISON_CUSTOM, -}; /** * nic_event_fn_t - nic event handler prototype @@ -35,18 +16,5 @@ enum hnae3_event_type_custom { typedef void (*nic_event_fn_t) (struct net_device *netdev, enum hnae3_event_type_custom); -/** - * nic_register_event - register for nic event handling - * @event_call: nic event handler - * return 0 - success , negative - fail - */ -int nic_register_event(nic_event_fn_t event_call); - -/** - * nic_unregister_event - quit nic event handling - * return 0 - success , negative - fail - */ -int nic_unregister_event(void); - int hclge_init(void); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c new file mode 100644 index 000000000000..52c7f5085cfb --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright (c) 2023 Hisilicon Limited. + +#include "hclge_main.h" +#include "hnae3.h" +#include "hnae3_ext.h" +#include "hclge_cmd.h" +#include "hclge_ext.h" + +#define HCLGE_RESET_MAX_FAIL_CNT 5 + +static nic_event_fn_t nic_event_call; + +/* We use a lock to ensure that the address of the nic_event_call function + * is valid when it is called. Avoid null pointer exceptions caused by + * external unregister during invoking. + */ +static DEFINE_MUTEX(hclge_nic_event_lock); + +static int hclge_set_reset_task(struct hclge_dev *hdev, void *data, + size_t length) +{ + u32 *reset_level = (u32 *)data; + + if (length != sizeof(u32)) + return -EINVAL; + + dev_warn(&hdev->pdev->dev, "reset level is %u\n", *reset_level); + + /* request reset & schedule reset task */ + set_bit(*reset_level, &hdev->reset_request); + hclge_reset_task_schedule(hdev); + return 0; +} + +int hclge_ext_call_event(struct hclge_dev *hdev, + enum hnae3_event_type_custom event_t) +{ + if (event_t >= HNAE3_INVALID_EVENT_CUSTOM) + return -EINVAL; + + mutex_lock(&hclge_nic_event_lock); + if (!nic_event_call) { + mutex_unlock(&hclge_nic_event_lock); + return -EOPNOTSUPP; + } + + nic_event_call(hdev->vport[0].nic.netdev, event_t); + mutex_unlock(&hclge_nic_event_lock); + return 0; +} + +int nic_register_event(nic_event_fn_t event_call) +{ + if (!event_call) { + pr_err("hns3: register event handle is null\n"); + return -EINVAL; + } + + mutex_lock(&hclge_nic_event_lock); + if (nic_event_call) { + mutex_unlock(&hclge_nic_event_lock); + pr_err("hns3: event already register\n"); + return -EBUSY; + } + + nic_event_call = event_call; + + mutex_unlock(&hclge_nic_event_lock); + pr_info("hns3: event register success\n"); + return 0; +} +EXPORT_SYMBOL(nic_register_event); + +int nic_unregister_event(void) +{ + mutex_lock(&hclge_nic_event_lock); + nic_event_call = NULL; + + mutex_unlock(&hclge_nic_event_lock); + pr_info("hns3: event unregister success\n"); + return 0; +} +EXPORT_SYMBOL(nic_unregister_event); + +static int hclge_nic_call_event(struct hclge_dev *hdev, void *data, + size_t length) +{ +#define ERROR_EVENT_TYPE_NUM 3 + + u32 event_type[ERROR_EVENT_TYPE_NUM] = { + HNAE3_PPU_POISON_CUSTOM, + HNAE3_IMP_RESET_CUSTOM, + HNAE3_IMP_RD_POISON_CUSTOM + }; + u32 *index = (u32 *)data; + + if (length != sizeof(u32)) + return -EINVAL; + + if ((*index) >= ERROR_EVENT_TYPE_NUM) + return 0; + + return hclge_ext_call_event(hdev, event_type[*index]); +} + +static enum hnae3_event_type_custom +hclge_get_reset_fail_type(enum hnae3_reset_type reset_type) +{ + const struct hclge_reset_fail_type_map fail_type_map[] = { + {HNAE3_FUNC_RESET, HNAE3_FUNC_RESET_FAIL_CUSTOM}, + {HNAE3_GLOBAL_RESET, HNAE3_GLOBAL_RESET_FAIL_CUSTOM}, + {HNAE3_IMP_RESET, HNAE3_IMP_RESET_FAIL_CUSTOM}, + }; + u32 i; + + for (i = 0; i < ARRAY_SIZE(fail_type_map); i++) + if (fail_type_map[i].reset_type == reset_type) + return fail_type_map[i].custom_type; + + return HNAE3_INVALID_EVENT_CUSTOM; +} + +static void hclge_report_reset_fail_custom(struct hclge_dev *hdev) +{ +#define HCLGE_RESET_MAX_FAIL_CNT_CUSTOM 1 + + u32 max_fail_custom_cnt = HCLGE_RESET_MAX_FAIL_CNT; + + mutex_lock(&hclge_nic_event_lock); + if (nic_event_call) + max_fail_custom_cnt = HCLGE_RESET_MAX_FAIL_CNT_CUSTOM; + mutex_unlock(&hclge_nic_event_lock); + + if (hdev->rst_stats.reset_fail_cnt < max_fail_custom_cnt) + return; + + dev_err(&hdev->pdev->dev, "failed to report reset!\n"); + hclge_ext_call_event(hdev, hclge_get_reset_fail_type(hdev->reset_type)); +} + +void hclge_ext_reset_end(struct hclge_dev *hdev, bool done) +{ + if (!done) { + hclge_report_reset_fail_custom(hdev); + return; + } + + hclge_ext_call_event(hdev, HNAE3_RESET_DONE_CUSTOM); + dev_info(&hdev->pdev->dev, "report reset done!\n"); +} + +static const hclge_priv_ops_fn hclge_ext_func_arr[] = { + [HNAE3_EXT_OPC_RESET] = hclge_set_reset_task, + [HNAE3_EXT_OPC_EVENT_CALLBACK] = hclge_nic_call_event, +}; + +int hclge_ext_ops_handle(struct hnae3_handle *handle, int opcode, + void *data, size_t length) +{ + struct hclge_vport *vport = hclge_get_vport(handle); + int cmd_num = ARRAY_SIZE(hclge_ext_func_arr); + struct hclge_dev *hdev = vport->back; + hclge_priv_ops_fn ext_opcode_func; + + if (opcode >= cmd_num) { + dev_err(&hdev->pdev->dev, "invalid opcode %d\n", opcode); + return -EINVAL; + } + + ext_opcode_func = hclge_ext_func_arr[opcode]; + if (!ext_opcode_func) { + dev_err(&hdev->pdev->dev, "unsupported opcode %d\n", opcode); + return -EOPNOTSUPP; + } + + return ext_opcode_func(hdev, data, length); +} diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h new file mode 100644 index 000000000000..1c1b04765e7e --- /dev/null +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ext.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* Copyright (c) 2016-2017 Hisilicon Limited. */ + +#ifndef __HCLGE_EXT_H +#define __HCLGE_EXT_H +#include + +struct hclge_reset_fail_type_map { + enum hnae3_reset_type reset_type; + enum hnae3_event_type_custom custom_type; +}; + +typedef int (*hclge_priv_ops_fn)(struct hclge_dev *hdev, void *data, + size_t length); + +/** + * nic_event_fn_t - nic event handler prototype + * @netdev: net device + * @hnae3_event_type_custom: nic device event type + */ +typedef void (*nic_event_fn_t) (struct net_device *netdev, + enum hnae3_event_type_custom); + +/** + * nic_register_event - register for nic event handling + * @event_call: nic event handler + * return 0 - success , negative - fail + */ +int nic_register_event(nic_event_fn_t event_call); + +/** + * nic_unregister_event - unregister for nic event handling + * return 0 - success , negative - fail + */ +int nic_unregister_event(void); + +int hclge_ext_call_event(struct hclge_dev *hdev, + enum hnae3_event_type_custom event_t); +void hclge_ext_reset_end(struct hclge_dev *hdev, bool done); + +int hclge_ext_ops_handle(struct hnae3_handle *handle, int opcode, + void *data, size_t length); +#endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index bbc63c47d0df..3779181b8f59 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -18,6 +18,7 @@ #include "kcompat.h" #include "hclge_cmd.h" #include "hclge_dcb.h" +#include "hclge_ext.h" #include "hclge_main.h" #include "hclge_mbx.h" #include "hclge_mdio.h" @@ -34,7 +35,6 @@ #define BUF_MAX_PERCENT 100 #define BUF_RESERVE_PERCENT 90 -#define HCLGE_RESET_MAX_FAIL_CNT 5 #define HCLGE_RESET_SYNC_TIME 100 #define HCLGE_PF_RESET_SYNC_TIME 20 #define HCLGE_PF_RESET_SYNC_CNT 1500 @@ -55,6 +55,8 @@ #define HCLGE_LINK_STATUS_MS 10 +#define HCLGE_RESET_MAX_FAIL_CNT 5 + static int hclge_set_mac_mtu(struct hclge_dev *hdev, int new_mps); static int hclge_init_vlan_config(struct hclge_dev *hdev); static void hclge_sync_vlan_filter(struct hclge_dev *hdev); @@ -67,6 +69,7 @@ static int hclge_set_default_loopback(struct hclge_dev *hdev); static void hclge_sync_mac_table(struct hclge_dev *hdev); static void hclge_restore_hw_table(struct hclge_dev *hdev); static void hclge_sync_promisc_mode(struct hclge_dev *hdev); +static void hclge_reset_end(struct hnae3_handle *handle, bool done); static struct hnae3_ae_algo ae_algo; @@ -2916,7 +2919,7 @@ static void hclge_mbx_task_schedule(struct hclge_dev *hdev) } } -static void hclge_reset_task_schedule(struct hclge_dev *hdev) +void hclge_reset_task_schedule(struct hclge_dev *hdev) { if (!test_bit(HCLGE_STATE_REMOVING, &hdev->state) && test_bit(HCLGE_STATE_SERVICE_INITED, &hdev->state) && @@ -3399,7 +3402,7 @@ static int hclge_get_status(struct hnae3_handle *handle) return hdev->hw.mac.link; } -static struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf) +struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf) { if (!pci_num_vf(hdev->pdev)) { dev_err(&hdev->pdev->dev, @@ -4142,8 +4145,7 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev) /* recover the handshake status when reset fail */ hclge_reset_handshake(hdev, true); - if (handle && handle->ae_algo->ops->reset_end) - handle->ae_algo->ops->reset_end(handle, false); + hclge_reset_end(handle, false); hclge_show_rst_info(hdev); @@ -4262,6 +4264,7 @@ static int hclge_reset_prepare(struct hclge_dev *hdev) static int hclge_reset_rebuild(struct hclge_dev *hdev) { + struct hnae3_handle *handle = &hdev->vport[0].nic; int ret; hdev->rst_stats.hw_reset_done_cnt++; @@ -4307,6 +4310,8 @@ static int hclge_reset_rebuild(struct hclge_dev *hdev) hclge_update_reset_level(hdev); + hclge_reset_end(handle, true); + return 0; } @@ -4328,10 +4333,11 @@ static void hclge_reset(struct hclge_dev *hdev) hclge_reset_task_schedule(hdev); } -static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) +void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) { struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); struct hclge_dev *hdev = ae_dev->priv; + int ret; /* We might end up getting called broadly because of 2 below cases: * 1. Recoverable error was conveyed through APEI and only way to bring @@ -4366,9 +4372,12 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) dev_info(&hdev->pdev->dev, "received reset event, reset type is %d\n", hdev->reset_level); - /* request reset & schedule reset task */ - set_bit(hdev->reset_level, &hdev->reset_request); - hclge_reset_task_schedule(hdev); + ret = hclge_ext_call_event(hdev, hdev->reset_level); + if (ret) { + /* request reset & schedule reset task */ + set_bit(hdev->reset_level, &hdev->reset_request); + hclge_reset_task_schedule(hdev); + } if (hdev->reset_level < HNAE3_GLOBAL_RESET) hdev->reset_level++; @@ -4385,7 +4394,6 @@ static void hclge_set_def_reset_request(struct hnae3_ae_dev *ae_dev, static void hclge_reset_timer(struct timer_list *t) { struct hclge_dev *hdev = from_timer(hdev, t, reset_timer); - struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); /* if default_reset_request has no value, it means that this reset * request has already be handled, so just return here @@ -4395,20 +4403,15 @@ static void hclge_reset_timer(struct timer_list *t) dev_info(&hdev->pdev->dev, "triggering reset in reset timer\n"); - - if (ae_dev->ops->reset_event) - ae_dev->ops->reset_event(hdev->pdev, NULL); + hclge_reset_event(hdev->pdev, &hdev->vport[0].nic); } -static bool hclge_reset_end(struct hnae3_handle *handle, bool done) +static void hclge_reset_end(struct hnae3_handle *handle, bool done) { struct hclge_vport *vport = hclge_get_vport(handle); struct hclge_dev *hdev = vport->back; - if (hdev->rst_stats.reset_fail_cnt >= HCLGE_RESET_MAX_FAIL_CNT) - dev_err(&hdev->pdev->dev, "Reset fail!\n"); - - return done; + hclge_ext_reset_end(hdev, done); } static void hclge_reset_subtask(struct hclge_dev *hdev) @@ -4448,8 +4451,8 @@ static void hclge_handle_err_reset_request(struct hclge_dev *hdev) hclge_set_def_reset_request(ae_dev, reset_type); } - if (hdev->default_reset_request && ae_dev->ops->reset_event) - ae_dev->ops->reset_event(hdev->pdev, NULL); + if (hdev->default_reset_request) + hclge_reset_event(hdev->pdev, &hdev->vport[0].nic); /* enable interrupt after error handling complete */ hclge_enable_vector(&hdev->misc_vector, true); @@ -12836,7 +12839,6 @@ struct hnae3_ae_ops hclge_ops = { .set_timer_task = hclge_set_timer_task, .mac_connect_phy = hclge_mac_connect_phy, .mac_disconnect_phy = hclge_mac_disconnect_phy, - .reset_end = hclge_reset_end, .get_vf_config = hclge_get_vf_config, .set_vf_link_state = hclge_set_vf_link_state, .set_vf_spoofchk = hclge_set_vf_spoofchk, @@ -12853,6 +12855,7 @@ struct hnae3_ae_ops hclge_ops = { .get_link_diagnosis_info = hclge_get_link_diagnosis_info, .get_wol = hclge_get_wol, .set_wol = hclge_set_wol, + .priv_ops = hclge_ext_ops_handle, }; static struct hnae3_ae_algo ae_algo = { diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 9d739033daab..f32c8b52f022 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -11,7 +11,7 @@ #include "hclge_cmd.h" #include "hclge_ptp.h" -#include "hnae3.h" +#include "hnae3_ext.h" #define HCLGE_MOD_VERSION "24.2.1" #define HCLGE_DRIVER_NAME "hclge" @@ -1168,4 +1168,7 @@ void hclge_unregister_sysfs(struct hclge_dev *hdev); int hclge_cfg_mac_speed_dup_hw(struct hclge_dev *hdev, int speed, u8 duplex); int hclge_get_wol_supported_mode(struct hclge_dev *hdev, u32 *wol_supported); int hclge_get_wol_cfg(struct hclge_dev *hdev, u32 *mode); +struct hclge_vport *hclge_get_vf_vport(struct hclge_dev *hdev, int vf); +void hclge_reset_task_schedule(struct hclge_dev *hdev); +void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle); #endif diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c index 305f11c854bf..4c270073c607 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c @@ -802,7 +802,7 @@ static void hclge_handle_ncsi_error(struct hclge_dev *hdev) ae_dev->ops->set_default_reset_request(ae_dev, HNAE3_GLOBAL_RESET); dev_warn(&hdev->pdev->dev, "requesting reset due to NCSI error\n"); - ae_dev->ops->reset_event(hdev->pdev, NULL); + hclge_reset_event(hdev->pdev, &hdev->vport[0].nic); } static void hclge_handle_vf_tbl(struct hclge_vport *vport, -- 2.34.1