261 lines
8.2 KiB
Diff
261 lines
8.2 KiB
Diff
From 8e0dbcfa3542090d75c09d6aa2b95486e38c29f2 Mon Sep 17 00:00:00 2001
|
|
From: Jijie Shao <shaojijie@huawei.com>
|
|
Date: Fri, 12 May 2023 18:00:14 +0800
|
|
Subject: [PATCH 215/283] net: hns3: fix reset timeout when enable full VF
|
|
|
|
mainline inclusion
|
|
from mainline-v6.4-rc3
|
|
commit 6b45d5ff8c2c61baddd67d7510075ae121c5e704
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EN49
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=6b45d5ff8c2c61baddd67d7510075ae121c5e704
|
|
|
|
--------------------------------
|
|
|
|
The timeout of the cmdq reset command has been increased to
|
|
resolve the reset timeout issue in the full VF scenario.
|
|
The timeout of other cmdq commands remains unchanged.
|
|
|
|
Fixes: 8d307f8e8cf1 ("net: hns3: create new set of unified hclge_comm_cmd_send APIs")
|
|
Signed-off-by: Jijie Shao <shaojijie@huawei.com>
|
|
Signed-off-by: Hao Lan <lanhao@huawei.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Signed-off-by: Jiantao Xiao <xiaojiantao1@h-partners.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
|
|
Conflicts:
|
|
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
|
|
---
|
|
.../hns3/hns3_common/hclge_comm_cmd.c | 167 +++++++++++++++++-
|
|
.../hns3/hns3_common/hclge_comm_cmd.h | 8 +-
|
|
2 files changed, 171 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
|
|
index 2cb06661bef9..a27736cde913 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
|
|
@@ -330,9 +330,25 @@ static int hclge_comm_cmd_csq_done(struct hclge_comm_hw *hw)
|
|
return head == hw->cmq.csq.next_to_use;
|
|
}
|
|
|
|
-static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
|
|
+static u32 hclge_get_cmdq_tx_timeout(u16 opcode, u32 tx_timeout)
|
|
+{
|
|
+ static const struct hclge_cmdq_tx_timeout_map cmdq_tx_timeout_map[] = {
|
|
+ {HCLGE_OPC_CFG_RST_TRIGGER, HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS},
|
|
+ };
|
|
+ u32 i;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(cmdq_tx_timeout_map); i++)
|
|
+ if (cmdq_tx_timeout_map[i].opcode == opcode)
|
|
+ return cmdq_tx_timeout_map[i].tx_timeout;
|
|
+
|
|
+ return tx_timeout;
|
|
+}
|
|
+
|
|
+static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw, u16 opcode,
|
|
bool *is_completed)
|
|
{
|
|
+ u32 cmdq_tx_timeout = hclge_get_cmdq_tx_timeout(opcode,
|
|
+ hw->cmq.tx_timeout);
|
|
u32 timeout = 0;
|
|
|
|
do {
|
|
@@ -342,7 +358,7 @@ static void hclge_comm_wait_for_resp(struct hclge_comm_hw *hw,
|
|
}
|
|
udelay(1);
|
|
timeout++;
|
|
- } while (timeout < hw->cmq.tx_timeout);
|
|
+ } while (timeout < cmdq_tx_timeout);
|
|
}
|
|
|
|
static int hclge_comm_cmd_convert_err_code(u16 desc_ret)
|
|
@@ -406,7 +422,8 @@ static int hclge_comm_cmd_check_result(struct hclge_comm_hw *hw,
|
|
* if multi descriptors to be sent, use the first one to check
|
|
*/
|
|
if (HCLGE_COMM_SEND_SYNC(le16_to_cpu(desc->flag)))
|
|
- hclge_comm_wait_for_resp(hw, &is_completed);
|
|
+ hclge_comm_wait_for_resp(hw, le16_to_cpu(desc->opcode),
|
|
+ &is_completed);
|
|
|
|
if (!is_completed)
|
|
ret = -EBADE;
|
|
@@ -475,3 +492,147 @@ int hclge_comm_cmd_send(struct hclge_comm_hw *hw, struct hclge_desc *desc,
|
|
|
|
return ret;
|
|
}
|
|
+
|
|
+static void hclge_comm_cmd_uninit_regs(struct hclge_comm_hw *hw)
|
|
+{
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CSQ_BASEADDR_L_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CSQ_BASEADDR_H_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CSQ_DEPTH_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CSQ_HEAD_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CSQ_TAIL_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CRQ_BASEADDR_L_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CRQ_BASEADDR_H_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CRQ_DEPTH_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CRQ_HEAD_REG, 0);
|
|
+ hclge_comm_write_dev(hw, HCLGE_COMM_NIC_CRQ_TAIL_REG, 0);
|
|
+}
|
|
+
|
|
+void hclge_comm_cmd_uninit(struct hnae3_ae_dev *ae_dev,
|
|
+ struct hclge_comm_hw *hw)
|
|
+{
|
|
+ struct hclge_comm_cmq *cmdq = &hw->cmq;
|
|
+
|
|
+ hclge_comm_firmware_compat_config(ae_dev, hw, false);
|
|
+ set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hw->comm_state);
|
|
+
|
|
+ /* wait to ensure that the firmware completes the possible left
|
|
+ * over commands.
|
|
+ */
|
|
+ msleep(HCLGE_COMM_CMDQ_CLEAR_WAIT_TIME);
|
|
+ spin_lock_bh(&cmdq->csq.lock);
|
|
+ spin_lock(&cmdq->crq.lock);
|
|
+ hclge_comm_cmd_uninit_regs(hw);
|
|
+ spin_unlock(&cmdq->crq.lock);
|
|
+ spin_unlock_bh(&cmdq->csq.lock);
|
|
+
|
|
+ hclge_comm_free_cmd_desc(&cmdq->csq);
|
|
+ hclge_comm_free_cmd_desc(&cmdq->crq);
|
|
+}
|
|
+
|
|
+int hclge_comm_cmd_queue_init(struct pci_dev *pdev, struct hclge_comm_hw *hw)
|
|
+{
|
|
+ struct hclge_comm_cmq *cmdq = &hw->cmq;
|
|
+ int ret;
|
|
+
|
|
+ /* Setup the lock for command queue */
|
|
+ spin_lock_init(&cmdq->csq.lock);
|
|
+ spin_lock_init(&cmdq->crq.lock);
|
|
+
|
|
+ cmdq->csq.pdev = pdev;
|
|
+ cmdq->crq.pdev = pdev;
|
|
+
|
|
+ /* Setup the queue entries for use cmd queue */
|
|
+ cmdq->csq.desc_num = HCLGE_COMM_NIC_CMQ_DESC_NUM;
|
|
+ cmdq->crq.desc_num = HCLGE_COMM_NIC_CMQ_DESC_NUM;
|
|
+
|
|
+ /* Setup Tx write back timeout */
|
|
+ cmdq->tx_timeout = HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT;
|
|
+
|
|
+ /* Setup queue rings */
|
|
+ ret = hclge_comm_alloc_cmd_queue(hw, HCLGE_COMM_TYPE_CSQ);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "CSQ ring setup error %d\n", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = hclge_comm_alloc_cmd_queue(hw, HCLGE_COMM_TYPE_CRQ);
|
|
+ if (ret) {
|
|
+ dev_err(&pdev->dev, "CRQ ring setup error %d\n", ret);
|
|
+ goto err_csq;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+err_csq:
|
|
+ hclge_comm_free_cmd_desc(&hw->cmq.csq);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int hclge_comm_cmd_init(struct hnae3_ae_dev *ae_dev, struct hclge_comm_hw *hw,
|
|
+ u32 *fw_version, bool is_pf,
|
|
+ unsigned long reset_pending)
|
|
+{
|
|
+ struct hclge_comm_cmq *cmdq = &hw->cmq;
|
|
+ int ret;
|
|
+
|
|
+ spin_lock_bh(&cmdq->csq.lock);
|
|
+ spin_lock(&cmdq->crq.lock);
|
|
+
|
|
+ cmdq->csq.next_to_clean = 0;
|
|
+ cmdq->csq.next_to_use = 0;
|
|
+ cmdq->crq.next_to_clean = 0;
|
|
+ cmdq->crq.next_to_use = 0;
|
|
+
|
|
+ hclge_comm_cmd_init_regs(hw);
|
|
+
|
|
+ spin_unlock(&cmdq->crq.lock);
|
|
+ spin_unlock_bh(&cmdq->csq.lock);
|
|
+
|
|
+ clear_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hw->comm_state);
|
|
+
|
|
+ /* Check if there is new reset pending, because the higher level
|
|
+ * reset may happen when lower level reset is being processed.
|
|
+ */
|
|
+ if (reset_pending) {
|
|
+ ret = -EBUSY;
|
|
+ goto err_cmd_init;
|
|
+ }
|
|
+
|
|
+ /* get version and device capabilities */
|
|
+ ret = hclge_comm_cmd_query_version_and_capability(ae_dev, hw,
|
|
+ fw_version, is_pf);
|
|
+ if (ret) {
|
|
+ dev_err(&ae_dev->pdev->dev,
|
|
+ "failed to query version and capabilities, ret = %d\n",
|
|
+ ret);
|
|
+ goto err_cmd_init;
|
|
+ }
|
|
+
|
|
+ dev_info(&ae_dev->pdev->dev,
|
|
+ "The firmware version is %lu.%lu.%lu.%lu\n",
|
|
+ hnae3_get_field(*fw_version, HNAE3_FW_VERSION_BYTE3_MASK,
|
|
+ HNAE3_FW_VERSION_BYTE3_SHIFT),
|
|
+ hnae3_get_field(*fw_version, HNAE3_FW_VERSION_BYTE2_MASK,
|
|
+ HNAE3_FW_VERSION_BYTE2_SHIFT),
|
|
+ hnae3_get_field(*fw_version, HNAE3_FW_VERSION_BYTE1_MASK,
|
|
+ HNAE3_FW_VERSION_BYTE1_SHIFT),
|
|
+ hnae3_get_field(*fw_version, HNAE3_FW_VERSION_BYTE0_MASK,
|
|
+ HNAE3_FW_VERSION_BYTE0_SHIFT));
|
|
+
|
|
+ if (!is_pf && ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3)
|
|
+ return 0;
|
|
+
|
|
+ /* ask the firmware to enable some features, driver can work without
|
|
+ * it.
|
|
+ */
|
|
+ ret = hclge_comm_firmware_compat_config(ae_dev, hw, true);
|
|
+ if (ret)
|
|
+ dev_warn(&ae_dev->pdev->dev,
|
|
+ "Firmware compatible features not enabled(%d).\n",
|
|
+ ret);
|
|
+ return 0;
|
|
+
|
|
+err_cmd_init:
|
|
+ set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hw->comm_state);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
|
|
index 8f07dc44b30a..81904010b96b 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
|
|
@@ -55,7 +55,8 @@
|
|
#define HCLGE_COMM_NIC_SW_RST_RDY BIT(HCLGE_COMM_NIC_SW_RST_RDY_B)
|
|
#define HCLGE_COMM_NIC_CMQ_DESC_NUM_S 3
|
|
#define HCLGE_COMM_NIC_CMQ_DESC_NUM 1024
|
|
-#define HCLGE_COMM_CMDQ_TX_TIMEOUT 30000
|
|
+#define HCLGE_COMM_CMDQ_TX_TIMEOUT_DEFAULT 30000
|
|
+#define HCLGE_COMM_CMDQ_TX_TIMEOUT_500MS 500000
|
|
|
|
enum hclge_opcode_type;
|
|
|
|
@@ -115,6 +116,11 @@ struct hclge_comm_caps_bit_map {
|
|
u16 local_bit;
|
|
};
|
|
|
|
+struct hclge_cmdq_tx_timeout_map {
|
|
+ u32 opcode;
|
|
+ u32 tx_timeout;
|
|
+};
|
|
+
|
|
struct hclge_comm_firmware_compat_cmd {
|
|
__le32 compat;
|
|
u8 rsv[20];
|
|
--
|
|
2.34.1
|
|
|