From 9bb15a3d0f9e33a6887ce6c0985108a2e4e0b14b Mon Sep 17 00:00:00 2001 From: Dengdui Huang Date: Mon, 27 Nov 2023 21:39:03 +0800 Subject: [PATCH] net/hns3: fix VF reset handler interruption [ upstream commit 94cf4db1603fe9074b5275cc4b63685fc91fdac5 ] Currently, the VF reset interrupt is enabled before the reset process is completed. If the VF reset is triggered by an IMP reset, the initialization of IMP is may not completed, and the VF reset interrupt may continue to be reported. In this scenario, the VF reset being performed by the driver does not need to be interrupted. Therefore, for VF reset, the driver has to enable the interrupt after the end of reset. Fixes: a5475d61fa34 ("net/hns3: support VF") Signed-off-by: Dengdui Huang Acked-by: Jie Hai --- drivers/net/hns3/hns3_ethdev.h | 12 ++++++++++++ drivers/net/hns3/hns3_ethdev_vf.c | 19 +++++++++++++++++-- drivers/net/hns3/hns3_intr.c | 3 +-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index 093d11cd71..5ba9503bf8 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -1036,6 +1036,7 @@ 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); +void hns3vf_clear_reset_event(struct hns3_hw *hw); static inline bool is_reset_pending(struct hns3_adapter *hns) @@ -1048,4 +1049,15 @@ is_reset_pending(struct hns3_adapter *hns) return ret; } +static inline void +hns3_clear_reset_status(struct hns3_hw *hw) +{ + struct hns3_adapter *hns = HNS3_DEV_HW_TO_ADAPTER(hw); + + if (hns->is_vf) + hns3vf_clear_reset_event(hw); + else + hns3_clear_reset_event(hw); +} + #endif /* _HNS3_ETHDEV_H_ */ diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index 5b76aad261..0d1d271f37 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -611,6 +611,19 @@ hns3vf_enable_irq0(struct hns3_hw *hw) hns3_write_dev(hw, HNS3_MISC_VECTOR_REG_BASE, 1); } +void +hns3vf_clear_reset_event(struct hns3_hw *hw) +{ + uint32_t clearval; + uint32_t cmdq_stat_reg; + + cmdq_stat_reg = hns3_read_dev(hw, HNS3_VECTOR0_CMDQ_STAT_REG); + clearval = cmdq_stat_reg & ~BIT(HNS3_VECTOR0_RST_INT_B); + hns3_write_dev(hw, HNS3_VECTOR0_CMDQ_SRC_REG, clearval); + + hns3vf_enable_irq0(hw); +} + static enum hns3vf_evt_cause hns3vf_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval) { @@ -685,8 +698,10 @@ hns3vf_interrupt_handler(void *param) break; } - /* Enable interrupt */ - hns3vf_enable_irq0(hw); + /* Enable interrupt if it is not caused by reset */ + if (event_cause == HNS3VF_VECTOR0_EVENT_MBX || + event_cause == HNS3VF_VECTOR0_EVENT_OTHER) + hns3vf_enable_irq0(hw); } void diff --git a/drivers/net/hns3/hns3_intr.c b/drivers/net/hns3/hns3_intr.c index 9c5a4b018c..b049774e9a 100644 --- a/drivers/net/hns3/hns3_intr.c +++ b/drivers/net/hns3/hns3_intr.c @@ -2730,8 +2730,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); - if (!hns->is_vf) - hns3_clear_reset_event(hw); + hns3_clear_reset_status(hw); __atomic_store_n(&hns->hw.reset.resetting, 0, __ATOMIC_RELAXED); hw->reset.attempts = 0; hw->reset.stats.success_cnt++;