From 1819e40908ee76c7219287224c22c772556c927e Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2018 14:07:51 +0100 Subject: net: hns3: Fix for VF mailbox cannot receiving PF response When the VF frequently switches the CMDQ interrupt, if the CMDQ_SRC is not cleared, the VF will not receive the new PF response after the interrupt is re-enabled, the corresponding log is as follows: [ 317.482222] hns3 0000:00:03.0: VF could not get mbx resp(=0) from PF in 500 tries [ 317.483137] hns3 0000:00:03.0: VF request to get tqp info from PF failed -5 This patch fixes this problem by clearing CMDQ_SRC before enabling interrupt and syncing pending IRQ handlers after disabling interrupt. Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") Signed-off-by: Xi Wang Signed-off-by: Peng Li Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index bc8a5760d959..a17872aab168 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -1565,6 +1565,8 @@ static int hclgevf_misc_irq_init(struct hclgevf_dev *hdev) return ret; } + hclgevf_clear_event_cause(hdev, 0); + /* enable misc. vector(vector 0) */ hclgevf_enable_vector(&hdev->misc_vector, true); @@ -1575,6 +1577,7 @@ static void hclgevf_misc_irq_uninit(struct hclgevf_dev *hdev) { /* disable misc vector(vector 0) */ hclgevf_enable_vector(&hdev->misc_vector, false); + synchronize_irq(hdev->misc_vector.vector_irq); free_irq(hdev->misc_vector.vector_irq, hdev); hclgevf_free_vector(hdev, 0); } -- cgit v1.2.3 From 6444e2a5f1e680278b58ced3568bdff84afe14a5 Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2018 14:07:52 +0100 Subject: net: hns3: Fix for VF mailbox receiving unknown message Before the firmware updates the crq's tail pointer, if the VF driver reads the data in the crq, the data may be incomplete at this time, which will lead to the driver read an unknown message. This patch fixes it by checking if crq is empty before reading the message. Fixes: b11a0bb231f3 ("net: hns3: Add mailbox support to VF driver") Signed-off-by: Xi Wang Signed-off-by: Peng Li Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- .../ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c index a28618428338..b598c06af8e0 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c @@ -126,6 +126,13 @@ int hclgevf_send_mbx_msg(struct hclgevf_dev *hdev, u16 code, u16 subcode, return status; } +static bool hclgevf_cmd_crq_empty(struct hclgevf_hw *hw) +{ + u32 tail = hclgevf_read_dev(hw, HCLGEVF_NIC_CRQ_TAIL_REG); + + return tail == hw->cmq.crq.next_to_use; +} + void hclgevf_mbx_handler(struct hclgevf_dev *hdev) { struct hclgevf_mbx_resp_status *resp; @@ -140,11 +147,22 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev) resp = &hdev->mbx_resp; crq = &hdev->hw.cmq.crq; - flag = le16_to_cpu(crq->desc[crq->next_to_use].flag); - while (hnae_get_bit(flag, HCLGEVF_CMDQ_RX_OUTVLD_B)) { + while (!hclgevf_cmd_crq_empty(&hdev->hw)) { desc = &crq->desc[crq->next_to_use]; req = (struct hclge_mbx_pf_to_vf_cmd *)desc->data; + flag = le16_to_cpu(crq->desc[crq->next_to_use].flag); + if (unlikely(!hnae_get_bit(flag, HCLGEVF_CMDQ_RX_OUTVLD_B))) { + dev_warn(&hdev->pdev->dev, + "dropped invalid mailbox message, code = %d\n", + req->msg[0]); + + /* dropping/not processing this invalid message */ + crq->desc[crq->next_to_use].flag = 0; + hclge_mbx_ring_ptr_move_crq(crq); + continue; + } + /* synchronous messages are time critical and need preferential * treatment. Therefore, we need to acknowledge all the sync * responses as quickly as possible so that waiting tasks do not @@ -205,7 +223,6 @@ void hclgevf_mbx_handler(struct hclgevf_dev *hdev) } crq->desc[crq->next_to_use].flag = 0; hclge_mbx_ring_ptr_move_crq(crq); - flag = le16_to_cpu(crq->desc[crq->next_to_use].flag); } /* Write back CMDQ_RQ header pointer, M7 need this pointer */ -- cgit v1.2.3 From 8e52a602b5126183f7a6487c4d48f6a00af4e4fd Mon Sep 17 00:00:00 2001 From: Xi Wang Date: Wed, 6 Jun 2018 14:07:53 +0100 Subject: net: hns3: Optimize PF CMDQ interrupt switching process When the PF frequently switches the CMDQ interrupt, if the CMDQ_SRC is not cleared before the hardware interrupt is generated, the new interrupt will not be reported. This patch optimizes this problem by clearing CMDQ_SRC and RESET_STS before enabling interrupt and syncing pending IRQ handlers after disabling interrupt. Fixes: 466b0c00391b ("net: hns3: Add support for misc interrupt") Signed-off-by: Xi Wang Signed-off-by: Peng Li Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2a801344eafb..d318d35e598f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2557,6 +2557,15 @@ static void hclge_clear_event_cause(struct hclge_dev *hdev, u32 event_type, } } +static void hclge_clear_all_event_cause(struct hclge_dev *hdev) +{ + hclge_clear_event_cause(hdev, HCLGE_VECTOR0_EVENT_RST, + BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B) | + BIT(HCLGE_VECTOR0_CORERESET_INT_B) | + BIT(HCLGE_VECTOR0_IMPRESET_INT_B)); + hclge_clear_event_cause(hdev, HCLGE_VECTOR0_EVENT_MBX, 0); +} + static void hclge_enable_vector(struct hclge_misc_vector *vector, bool enable) { writel(enable ? 1 : 0, vector->addr); @@ -5688,6 +5697,8 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev) INIT_WORK(&hdev->rst_service_task, hclge_reset_service_task); INIT_WORK(&hdev->mbx_service_task, hclge_mailbox_service_task); + hclge_clear_all_event_cause(hdev); + /* Enable MISC vector(vector0) */ hclge_enable_vector(&hdev->misc_vector, true); @@ -5817,6 +5828,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev) /* Disable MISC vector(vector0) */ hclge_enable_vector(&hdev->misc_vector, false); + synchronize_irq(hdev->misc_vector.vector_irq); + hclge_destroy_cmd_queue(&hdev->hw); hclge_misc_irq_uninit(hdev); hclge_pci_uninit(hdev); -- cgit v1.2.3