Commit 13050921 authored by Huazhong Tan's avatar Huazhong Tan Committed by David S. Miller

net: hns3: fix interrupt clearing error for VF

Currently, VF driver has two kinds of interrupts, reset & CMDQ RX.
For revision 0x21, according to the UM, each interrupt should be
cleared by write 0 to the corresponding bit, but the implementation
writes 0 to the whole register in fact, it will clear other
interrupt at the same time, then the VF will loss the interrupt.
But for revision 0x20, this interrupt clear register is a read &
write register, for compatible, we just keep the old implementation
for 0x20.

This patch fixes it, also, adds a new register for reading the interrupt
status according to hardware user manual.

Fixes: e2cb1dec ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support")
Fixes: b90fcc5b ("net: hns3: add reset handling for VF when doing Core/Global/IMP reset")
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Reviewed-by: default avatarYunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9e6717af
...@@ -1889,21 +1889,20 @@ static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr) ...@@ -1889,21 +1889,20 @@ static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr)
static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
u32 *clearval) u32 *clearval)
{ {
u32 val, cmdq_src_reg, rst_ing_reg; u32 val, cmdq_stat_reg, rst_ing_reg;
/* fetch the events from their corresponding regs */ /* fetch the events from their corresponding regs */
cmdq_src_reg = hclgevf_read_dev(&hdev->hw, cmdq_stat_reg = hclgevf_read_dev(&hdev->hw,
HCLGEVF_VECTOR0_CMDQ_SRC_REG); HCLGEVF_VECTOR0_CMDQ_STAT_REG);
if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_src_reg) { if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) {
rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING); rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
dev_info(&hdev->pdev->dev, dev_info(&hdev->pdev->dev,
"receive reset interrupt 0x%x!\n", rst_ing_reg); "receive reset interrupt 0x%x!\n", rst_ing_reg);
set_bit(HNAE3_VF_RESET, &hdev->reset_pending); set_bit(HNAE3_VF_RESET, &hdev->reset_pending);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state); set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state); set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RST_INT_B); *clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
*clearval = cmdq_src_reg;
hdev->rst_stats.vf_rst_cnt++; hdev->rst_stats.vf_rst_cnt++;
/* set up VF hardware reset status, its PF will clear /* set up VF hardware reset status, its PF will clear
* this status when PF has initialized done. * this status when PF has initialized done.
...@@ -1915,9 +1914,20 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev, ...@@ -1915,9 +1914,20 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
} }
/* check for vector0 mailbox(=CMDQ RX) event source */ /* check for vector0 mailbox(=CMDQ RX) event source */
if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_src_reg) { if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_stat_reg) {
cmdq_src_reg &= ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B); /* for revision 0x21, clearing interrupt is writing bit 0
*clearval = cmdq_src_reg; * to the clear register, writing bit 1 means to keep the
* old value.
* for revision 0x20, the clear register is a read & write
* register, so we should just write 0 to the bit we are
* handling, and keep other bits as cmdq_stat_reg.
*/
if (hdev->pdev->revision >= 0x21)
*clearval = ~(1U << HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
else
*clearval = cmdq_stat_reg &
~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
return HCLGEVF_VECTOR0_EVENT_MBX; return HCLGEVF_VECTOR0_EVENT_MBX;
} }
......
...@@ -87,6 +87,8 @@ ...@@ -87,6 +87,8 @@
/* Vector0 interrupt CMDQ event source register(RW) */ /* Vector0 interrupt CMDQ event source register(RW) */
#define HCLGEVF_VECTOR0_CMDQ_SRC_REG 0x27100 #define HCLGEVF_VECTOR0_CMDQ_SRC_REG 0x27100
/* Vector0 interrupt CMDQ event status register(RO) */
#define HCLGEVF_VECTOR0_CMDQ_STAT_REG 0x27104
/* CMDQ register bits for RX event(=MBX event) */ /* CMDQ register bits for RX event(=MBX event) */
#define HCLGEVF_VECTOR0_RX_CMDQ_INT_B 1 #define HCLGEVF_VECTOR0_RX_CMDQ_INT_B 1
/* RST register bits for RESET event */ /* RST register bits for RESET event */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment