Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ada13ee3 authored by Huazhong Tan's avatar Huazhong Tan Committed by David S. Miller
Browse files

net: hns3: add handshake with hardware while doing reset



When reset happens, the hardware reset should begin after the
driver has finished its preparatory work, otherwise it may cause
some hardware error.

Before Hardware's reset, it will wait for the driver to write
bit HCLGE_NIC_CMQ_ENABLE of register HCLGE_NIC_CSQ_DEPTH_REG
to 1, while the driver finishes its preparatory work will do that.
BTW, since some cases this register will be cleared, so it needs
some sync time before driver's writing.

Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1db58f86
Loading
Loading
Loading
Loading
+2 −4
Original line number Original line Diff line number Diff line
@@ -110,8 +110,7 @@ static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
		hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG,
		hclge_write_dev(hw, HCLGE_NIC_CSQ_BASEADDR_H_REG,
				upper_32_bits(dma));
				upper_32_bits(dma));
		hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG,
		hclge_write_dev(hw, HCLGE_NIC_CSQ_DEPTH_REG,
				(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
				ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S);
				HCLGE_NIC_CMQ_ENABLE);
		hclge_write_dev(hw, HCLGE_NIC_CSQ_HEAD_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_CSQ_TAIL_REG, 0);
	} else {
	} else {
@@ -120,8 +119,7 @@ static void hclge_cmd_config_regs(struct hclge_cmq_ring *ring)
		hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG,
		hclge_write_dev(hw, HCLGE_NIC_CRQ_BASEADDR_H_REG,
				upper_32_bits(dma));
				upper_32_bits(dma));
		hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG,
		hclge_write_dev(hw, HCLGE_NIC_CRQ_DEPTH_REG,
				(ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S) |
				ring->desc_num >> HCLGE_NIC_CMQ_DESC_NUM_S);
				HCLGE_NIC_CMQ_ENABLE);
		hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
		hclge_write_dev(hw, HCLGE_NIC_CRQ_HEAD_REG, 0);
		hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
		hclge_write_dev(hw, HCLGE_NIC_CRQ_TAIL_REG, 0);
	}
	}
+8 −2
Original line number Original line Diff line number Diff line
@@ -3197,6 +3197,8 @@ static int hclge_reset_prepare_down(struct hclge_dev *hdev)


static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
{
{
#define HCLGE_RESET_SYNC_TIME 100

	u32 reg_val;
	u32 reg_val;
	int ret = 0;
	int ret = 0;


@@ -3205,7 +3207,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
		/* There is no mechanism for PF to know if VF has stopped IO
		/* There is no mechanism for PF to know if VF has stopped IO
		 * for now, just wait 100 ms for VF to stop IO
		 * for now, just wait 100 ms for VF to stop IO
		 */
		 */
		msleep(100);
		msleep(HCLGE_RESET_SYNC_TIME);
		ret = hclge_func_reset_cmd(hdev, 0);
		ret = hclge_func_reset_cmd(hdev, 0);
		if (ret) {
		if (ret) {
			dev_err(&hdev->pdev->dev,
			dev_err(&hdev->pdev->dev,
@@ -3225,7 +3227,7 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
		/* There is no mechanism for PF to know if VF has stopped IO
		/* There is no mechanism for PF to know if VF has stopped IO
		 * for now, just wait 100 ms for VF to stop IO
		 * for now, just wait 100 ms for VF to stop IO
		 */
		 */
		msleep(100);
		msleep(HCLGE_RESET_SYNC_TIME);
		set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
		set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
		set_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
		set_bit(HNAE3_FLR_DOWN, &hdev->flr_state);
		hdev->rst_stats.flr_rst_cnt++;
		hdev->rst_stats.flr_rst_cnt++;
@@ -3239,6 +3241,10 @@ static int hclge_reset_prepare_wait(struct hclge_dev *hdev)
		break;
		break;
	}
	}


	/* inform hardware that preparatory work is done */
	msleep(HCLGE_RESET_SYNC_TIME);
	hclge_write_dev(&hdev->hw, HCLGE_NIC_CSQ_DEPTH_REG,
			HCLGE_NIC_CMQ_ENABLE);
	dev_info(&hdev->pdev->dev, "prepare wait ok\n");
	dev_info(&hdev->pdev->dev, "prepare wait ok\n");


	return ret;
	return ret;
+0 −2
Original line number Original line Diff line number Diff line
@@ -98,7 +98,6 @@ static void hclgevf_cmd_config_regs(struct hclgevf_cmq_ring *ring)
		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, reg_val);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_BASEADDR_H_REG, reg_val);


		reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S);
		reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S);
		reg_val |= HCLGEVF_NIC_CMQ_ENABLE;
		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, reg_val);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_DEPTH_REG, reg_val);


		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CSQ_HEAD_REG, 0);
@@ -110,7 +109,6 @@ static void hclgevf_cmd_config_regs(struct hclgevf_cmq_ring *ring)
		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, reg_val);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_BASEADDR_H_REG, reg_val);


		reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S);
		reg_val = (ring->desc_num >> HCLGEVF_NIC_CMQ_DESC_NUM_S);
		reg_val |= HCLGEVF_NIC_CMQ_ENABLE;
		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_DEPTH_REG, reg_val);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_DEPTH_REG, reg_val);


		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_HEAD_REG, 0);
		hclgevf_write_dev(hw, HCLGEVF_NIC_CRQ_HEAD_REG, 0);
+6 −1
Original line number Original line Diff line number Diff line
@@ -1414,6 +1414,8 @@ static int hclgevf_reset_stack(struct hclgevf_dev *hdev)


static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
{
{
#define HCLGEVF_RESET_SYNC_TIME 100

	int ret = 0;
	int ret = 0;


	switch (hdev->reset_type) {
	switch (hdev->reset_type) {
@@ -1431,7 +1433,10 @@ static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
	}
	}


	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);

	/* inform hardware that preparatory work is done */
	msleep(HCLGEVF_RESET_SYNC_TIME);
	hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG,
			  HCLGEVF_NIC_CMQ_ENABLE);
	dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done, ret:%d\n",
	dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done, ret:%d\n",
		 hdev->reset_type, ret);
		 hdev->reset_type, ret);