Sync some patchs from upstreaming and modifies are as follow: - net/hns3: fix mailbox sync - net/hns3: report maximum buffer size - ethdev: add maximum Rx buffer size - app/procinfo: show RSS hash algorithm - ethdev: get RSS algorithm names - app/procinfo: adjust format of RSS info - app/procinfo: fix RSS info - net/hns3: support setting and querying RSS hash function - net/hns3: report RSS hash algorithms capability - ethdev: set and query RSS hash algorithm - ethdev: clarify RSS related fields usage - net/hns3: fix uninitialized hash algo value - net/hns3: keep set/get algo key functions local - net/hns3: fix some error logs - net/hns3: fix some return values - net/hns3: fix LRO offload to report - net/hns3: fix setting DCB capability - app/testpmd: ease configuring all offloads - net/hns3: refactor interrupt state query - net/hns3: fix IMP or global reset - net/hns3: fix multiple reset detected log - net/hns3: remove reset log in secondary - net/hns3: fix double stats for IMP and global reset - net/hns3: fix crash for NEON and SVE - net/hns3: fix unchecked Rx free threshold - net/hns3: fix typo in function name - net/hns3: fix build warning - telemetry: fix repeat display when callback don't init dict Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
230 lines
7.6 KiB
Diff
230 lines
7.6 KiB
Diff
From 2bf782a351fe9e5bd7155e5be9548fa2569aa6dc Mon Sep 17 00:00:00 2001
|
|
From: Dengdui Huang <huangdengdui@huawei.com>
|
|
Date: Fri, 27 Oct 2023 14:09:45 +0800
|
|
Subject: [PATCH 375/394] net/hns3: fix IMP or global reset
|
|
|
|
[ upstream commit 1eee1ea75c0eadaea6dde368b289cf0acf6a1190 ]
|
|
|
|
Currently, when the IMP or Global reset detected, the vector0
|
|
interrupt is enabled before the reset process is completed.
|
|
At this moment, if the initialization of IMP is not completed,
|
|
and the vector0 interrupt may continue to be reported. In this
|
|
scenario, the IMP/global reset being performed by the driver
|
|
does not need to be interrupted. Therefore, for IMP and global
|
|
resets, the driver has to enable the interrupt after the end
|
|
of reset.
|
|
|
|
The RAS interrupt is also shared with the vector0 interrupt.
|
|
When the interrupt is disabled, the RAS interrupt can still be
|
|
reported to the driver and the driver interrupt processing
|
|
function is also called. In this case, the interrupt status of
|
|
the IMP/global may still exist. Therefore, this patch also has
|
|
to the check of the new reset level based on the priority of
|
|
reset level in the interrupt handler.
|
|
|
|
Fixes: 2790c6464725 ("net/hns3: support device reset")
|
|
Fixes: 3988ab0eee52 ("net/hns3: add abnormal interrupt process")
|
|
Cc: stable@dpdk.org
|
|
|
|
Signed-off-by: Dengdui Huang <huangdengdui@huawei.com>
|
|
---
|
|
drivers/net/hns3/hns3_ethdev.c | 88 ++++++++++++++++++++++++++++------
|
|
drivers/net/hns3/hns3_ethdev.h | 1 +
|
|
drivers/net/hns3/hns3_intr.c | 2 +
|
|
3 files changed, 77 insertions(+), 14 deletions(-)
|
|
|
|
diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c
|
|
index 8c96c8a964..0f201b8b99 100644
|
|
--- a/drivers/net/hns3/hns3_ethdev.c
|
|
+++ b/drivers/net/hns3/hns3_ethdev.c
|
|
@@ -215,6 +215,30 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval)
|
|
return ret;
|
|
}
|
|
|
|
+void
|
|
+hns3_clear_reset_event(struct hns3_hw *hw)
|
|
+{
|
|
+ uint32_t clearval = 0;
|
|
+
|
|
+ switch (hw->reset.level) {
|
|
+ case HNS3_IMP_RESET:
|
|
+ clearval = BIT(HNS3_VECTOR0_IMPRESET_INT_B);
|
|
+ break;
|
|
+ case HNS3_GLOBAL_RESET:
|
|
+ clearval = BIT(HNS3_VECTOR0_GLOBALRESET_INT_B);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (clearval == 0)
|
|
+ return;
|
|
+
|
|
+ hns3_write_dev(hw, HNS3_MISC_RESET_STS_REG, clearval);
|
|
+
|
|
+ hns3_pf_enable_irq0(hw);
|
|
+}
|
|
+
|
|
static void
|
|
hns3_clear_event_cause(struct hns3_hw *hw, uint32_t event_type, uint32_t regclr)
|
|
{
|
|
@@ -287,6 +311,34 @@ hns3_delay_before_clear_event_cause(struct hns3_hw *hw, uint32_t event_type, uin
|
|
}
|
|
}
|
|
|
|
+static bool
|
|
+hns3_reset_event_valid(struct hns3_hw *hw)
|
|
+{
|
|
+ struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
|
|
+ enum hns3_reset_level new_req = HNS3_NONE_RESET;
|
|
+ enum hns3_reset_level last_req;
|
|
+ uint32_t vector0_int;
|
|
+
|
|
+ vector0_int = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG);
|
|
+ if (BIT(HNS3_VECTOR0_IMPRESET_INT_B) & vector0_int)
|
|
+ new_req = HNS3_IMP_RESET;
|
|
+ else if (BIT(HNS3_VECTOR0_GLOBALRESET_INT_B) & vector0_int)
|
|
+ new_req = HNS3_GLOBAL_RESET;
|
|
+ if (new_req == HNS3_NONE_RESET)
|
|
+ return true;
|
|
+
|
|
+ last_req = hns3_get_reset_level(hns, &hw->reset.pending);
|
|
+ if (last_req == HNS3_NONE_RESET)
|
|
+ return true;
|
|
+
|
|
+ if (new_req > last_req)
|
|
+ return true;
|
|
+
|
|
+ hns3_warn(hw, "last_req (%u) less than or equal to new_req (%u) ignore",
|
|
+ last_req, new_req);
|
|
+ return false;
|
|
+}
|
|
+
|
|
static void
|
|
hns3_interrupt_handler(void *param)
|
|
{
|
|
@@ -299,6 +351,9 @@ hns3_interrupt_handler(void *param)
|
|
uint32_t ras_int;
|
|
uint32_t cmdq_int;
|
|
|
|
+ if (!hns3_reset_event_valid(hw))
|
|
+ return;
|
|
+
|
|
/* Disable interrupt */
|
|
hns3_pf_disable_irq0(hw);
|
|
|
|
@@ -327,7 +382,11 @@ hns3_interrupt_handler(void *param)
|
|
}
|
|
|
|
/* Enable interrupt if it is not cause by reset */
|
|
- hns3_pf_enable_irq0(hw);
|
|
+ if (event_cause == HNS3_VECTOR0_EVENT_ERR ||
|
|
+ event_cause == HNS3_VECTOR0_EVENT_MBX ||
|
|
+ event_cause == HNS3_VECTOR0_EVENT_PTP ||
|
|
+ event_cause == HNS3_VECTOR0_EVENT_OTHER)
|
|
+ hns3_pf_enable_irq0(hw);
|
|
}
|
|
|
|
static int
|
|
@@ -5489,7 +5548,7 @@ is_pf_reset_done(struct hns3_hw *hw)
|
|
return true;
|
|
}
|
|
|
|
-static void
|
|
+static enum hns3_reset_level
|
|
hns3_detect_reset_event(struct hns3_hw *hw)
|
|
{
|
|
struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw);
|
|
@@ -5501,11 +5560,9 @@ hns3_detect_reset_event(struct hns3_hw *hw)
|
|
vector0_intr_state = hns3_read_dev(hw, HNS3_VECTOR0_OTHER_INT_STS_REG);
|
|
if (BIT(HNS3_VECTOR0_IMPRESET_INT_B) & vector0_intr_state) {
|
|
__atomic_store_n(&hw->reset.disable_cmd, 1, __ATOMIC_RELAXED);
|
|
- hns3_atomic_set_bit(HNS3_IMP_RESET, &hw->reset.pending);
|
|
new_req = HNS3_IMP_RESET;
|
|
} else if (BIT(HNS3_VECTOR0_GLOBALRESET_INT_B) & vector0_intr_state) {
|
|
__atomic_store_n(&hw->reset.disable_cmd, 1, __ATOMIC_RELAXED);
|
|
- hns3_atomic_set_bit(HNS3_GLOBAL_RESET, &hw->reset.pending);
|
|
new_req = HNS3_GLOBAL_RESET;
|
|
}
|
|
|
|
@@ -5513,13 +5570,16 @@ hns3_detect_reset_event(struct hns3_hw *hw)
|
|
hns3_schedule_delayed_reset(hns);
|
|
hns3_warn(hw, "High level reset detected, delay do reset");
|
|
}
|
|
+
|
|
+ return new_req;
|
|
}
|
|
|
|
bool
|
|
hns3_is_reset_pending(struct hns3_adapter *hns)
|
|
{
|
|
+ enum hns3_reset_level new_req;
|
|
struct hns3_hw *hw = &hns->hw;
|
|
- enum hns3_reset_level reset;
|
|
+ enum hns3_reset_level last_req;
|
|
|
|
/*
|
|
* Only primary can process can process the reset event,
|
|
@@ -5528,17 +5588,17 @@ hns3_is_reset_pending(struct hns3_adapter *hns)
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
return false;
|
|
|
|
- hns3_detect_reset_event(hw);
|
|
- reset = hns3_get_reset_level(hns, &hw->reset.pending);
|
|
- if (reset != HNS3_NONE_RESET && hw->reset.level != HNS3_NONE_RESET &&
|
|
- hw->reset.level < reset) {
|
|
- hns3_warn(hw, "High level reset %d is pending", reset);
|
|
+ new_req = hns3_detect_reset_event(hw);
|
|
+ last_req = hns3_get_reset_level(hns, &hw->reset.pending);
|
|
+ if (last_req != HNS3_NONE_RESET && new_req != HNS3_NONE_RESET &&
|
|
+ new_req < last_req) {
|
|
+ hns3_warn(hw, "High level reset %d is pending", last_req);
|
|
return true;
|
|
}
|
|
- reset = hns3_get_reset_level(hns, &hw->reset.request);
|
|
- if (reset != HNS3_NONE_RESET && hw->reset.level != HNS3_NONE_RESET &&
|
|
- hw->reset.level < reset) {
|
|
- hns3_warn(hw, "High level reset %d is request", reset);
|
|
+ last_req = hns3_get_reset_level(hns, &hw->reset.request);
|
|
+ if (last_req != HNS3_NONE_RESET && hw->reset.level != HNS3_NONE_RESET &&
|
|
+ hw->reset.level < last_req) {
|
|
+ hns3_warn(hw, "High level reset %d is request", last_req);
|
|
return true;
|
|
}
|
|
return false;
|
|
diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h
|
|
index c85a6912ad..0e8d043704 100644
|
|
--- a/drivers/net/hns3/hns3_ethdev.h
|
|
+++ b/drivers/net/hns3/hns3_ethdev.h
|
|
@@ -1033,6 +1033,7 @@ void hns3_update_linkstatus_and_event(struct hns3_hw *hw, bool query);
|
|
void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status,
|
|
uint32_t link_speed, uint8_t link_duplex);
|
|
void hns3vf_update_push_lsc_cap(struct hns3_hw *hw, bool supported);
|
|
+void hns3_clear_reset_event(struct hns3_hw *hw);
|
|
|
|
const char *hns3_get_media_type_name(uint8_t media_type);
|
|
|
|
diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c
|
|
index 51711244b5..ce8a28e2f9 100644
|
|
--- a/drivers/net/hns3/hns3_intr.c
|
|
+++ b/drivers/net/hns3/hns3_intr.c
|
|
@@ -2727,6 +2727,7 @@ hns3_reset_post(struct hns3_adapter *hns)
|
|
/* IMP will wait ready flag before reset */
|
|
hns3_notify_reset_ready(hw, false);
|
|
hns3_clear_reset_level(hw, &hw->reset.pending);
|
|
+ hns3_clear_reset_event(hw);
|
|
__atomic_store_n(&hns->hw.reset.resetting, 0, __ATOMIC_RELAXED);
|
|
hw->reset.attempts = 0;
|
|
hw->reset.stats.success_cnt++;
|
|
@@ -2775,6 +2776,7 @@ hns3_reset_fail_handle(struct hns3_adapter *hns)
|
|
struct timeval tv;
|
|
|
|
hns3_clear_reset_level(hw, &hw->reset.pending);
|
|
+ hns3_clear_reset_event(hw);
|
|
if (hns3_reset_err_handle(hns)) {
|
|
hw->reset.stage = RESET_STAGE_PREWAIT;
|
|
hns3_schedule_reset(hns);
|
|
--
|
|
2.23.0
|
|
|