net: hns3: uninitialize command queue while unloading PF driver
authorHuazhong Tan <tanhuazhong@huawei.com>
Wed, 20 Feb 2019 02:32:50 +0000 (10:32 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Feb 2019 00:29:05 +0000 (16:29 -0800)
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 <tanhuazhong@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

index 1dddfcba41a9e3889db51d440a67abd47fc5a186..3a093a92eac516ac40d12309371c3780dc7b20f4 100644 (file)
@@ -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);
+}
index ac2cd219a9fbd072c8e1bb33731fb098c17aa988..bad21c89f6b77e14b5322f89b6eadf11e3b3221c 100644 (file)
@@ -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
index 4a596460271c36205a3990c0577e464eff7802d1..5c8f2e4d71c98df7638d9e3fa45ebe17cb6c5239 100644 (file)
@@ -7669,7 +7669,7 @@ err_msi_irq_uninit:
 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);