According to the hardware's description, the driver should clear
the command queue's registers when uloading driver. Otherwise,
these existing value may lead the IMP get into a wrong state.

Also this patch adds hclge_cmd_uninit() to do the command queue
uninitialization which includes clearing registers and freeing
memory.

Fixes: 68c0a5c70614 ("net: hns3: Add HNS3 IMP(Integrated Mgmt Proc) Cmd 
Interface Support")
Signed-off-by: Huazhong Tan <tanhuazh...@huawei.com>
Signed-off-by: Peng Li <lipeng...@huawei.com>
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c | 26 ++++++++++++++++++++++
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h |  2 +-
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    |  4 ++--
 3 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
index 1dddfcb..3a093a9 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
@@ -390,6 +390,20 @@ int hclge_cmd_init(struct hclge_dev *hdev)
        return 0;
 }
 
+static void hclge_cmd_uninit_regs(struct hclge_hw *hw)
+{
+       hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_L_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CSQ_TAIL_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_L_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
+       hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
+}
+
 static void hclge_destroy_queue(struct hclge_cmq_ring *ring)
 {
        spin_lock(&ring->lock);
@@ -402,3 +416,15 @@ void hclge_destroy_cmd_queue(struct hclge_hw *hw)
        hclge_destroy_queue(&hw->cmq.csq);
        hclge_destroy_queue(&hw->cmq.crq);
 }
+
+void hclge_cmd_uninit(struct hclge_dev *hdev)
+{
+       spin_lock_bh(&hdev->hw.cmq.csq.lock);
+       spin_lock(&hdev->hw.cmq.crq.lock);
+       set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
+       hclge_cmd_uninit_regs(&hdev->hw);
+       spin_unlock(&hdev->hw.cmq.crq.lock);
+       spin_unlock_bh(&hdev->hw.cmq.csq.lock);
+
+       hclge_destroy_cmd_queue(&hdev->hw);
+}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index ac2cd21..bad21c89 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -975,6 +975,6 @@ enum hclge_cmd_status hclge_cmd_mdio_write(struct hclge_hw 
*hw,
 enum hclge_cmd_status hclge_cmd_mdio_read(struct hclge_hw *hw,
                                          struct hclge_desc *desc);
 
-void hclge_destroy_cmd_queue(struct hclge_hw *hw);
+void hclge_cmd_uninit(struct hclge_dev *hdev);
 int hclge_cmd_queue_init(struct hclge_dev *hdev);
 #endif
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 4a59646..5c8f2e4 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7669,7 +7669,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
 err_msi_uninit:
        pci_free_irq_vectors(pdev);
 err_cmd_uninit:
-       hclge_destroy_cmd_queue(&hdev->hw);
+       hclge_cmd_uninit(hdev);
 err_pci_uninit:
        pcim_iounmap(pdev, hdev->hw.io_base);
        pci_clear_master(pdev);
@@ -7796,7 +7796,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev 
*ae_dev)
        synchronize_irq(hdev->misc_vector.vector_irq);
 
        hclge_hw_error_set_state(hdev, false);
-       hclge_destroy_cmd_queue(&hdev->hw);
+       hclge_cmd_uninit(hdev);
        hclge_misc_irq_uninit(hdev);
        hclge_pci_uninit(hdev);
        mutex_destroy(&hdev->vport_lock);
-- 
2.7.4

Reply via email to