Commit 364d4bf5 authored by Weibo Zhao's avatar Weibo Zhao Committed by JiangShui
Browse files

hns3 udma: add function clear when ko rmmod

driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I85R2F


CVE: NA

---------------------------------------------

When rmmod ko and hw exit, function clear should
be done. Driver post a function clear command to
hardware to clean resource in function.

Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent 40b935d3
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -1110,6 +1110,74 @@ static int udma_hw_set_eid(struct udma_dev *udma_dev, union ubcore_eid eid)
	return ret;
}

static void __udma_function_clear(struct udma_dev *udma_dev, int vf_id)
{
	struct udma_func_clear *resp;
	struct udma_cmq_desc desc;
	uint64_t end;
	int ret = 0;

	udma_cmq_setup_basic_desc(&desc, UDMA_OPC_FUNC_CLEAR, false);
	resp = (struct udma_func_clear *)desc.data;
	resp->rst_funcid_en = cpu_to_le32(vf_id);

	ret = udma_cmq_send(udma_dev, &desc, 1);
	if (ret) {
		dev_err(udma_dev->dev, "Func clear write failed, ret = %d.\n",
			ret);
		return;
	}

	msleep(UDMA_READ_FUNC_CLEAR_FLAG_INTERVAL);
	end = UDMA_FUNC_CLEAR_TIMEOUT_MSECS;
	while (end) {
		msleep(UDMA_READ_FUNC_CLEAR_FLAG_FAIL_WAIT);
		end -= UDMA_READ_FUNC_CLEAR_FLAG_FAIL_WAIT;

		udma_cmq_setup_basic_desc(&desc, UDMA_OPC_FUNC_CLEAR,
					  true);

		resp->rst_funcid_en = cpu_to_le32(vf_id);
		ret = udma_cmq_send(udma_dev, &desc, 1);
		if (ret)
			continue;

		if (udma_get_bit(resp->func_done, FUNC_CLEAR_RST_FUN_DONE_S)) {
			if (vf_id == 0)
				udma_dev->is_reset = true;
			return;
		}
	}
}

static void udma_free_vf_resource(struct udma_dev *udma_dev, int vf_id)
{
	enum udma_opcode_type opcode = UDMA_OPC_ALLOC_VF_RES;
	struct udma_cmq_desc desc[2];
	struct udma_cmq_req *req_a;

	req_a = (struct udma_cmq_req *)desc[0].data;
	udma_cmq_setup_basic_desc(&desc[0], opcode, false);
	desc[0].flag |= cpu_to_le16(UDMA_CMD_FLAG_NEXT);
	udma_cmq_setup_basic_desc(&desc[1], opcode, false);
	udma_reg_write(req_a, FUNC_RES_A_VF_ID, vf_id);
	udma_cmq_send(udma_dev, desc, 2);
}

static void udma_function_clear(struct udma_dev *udma_dev)
{
	int i;

	if (udma_dev->cmd.state == UDMA_CMDQ_STATE_FATAL_ERR)
		return;

	for (i = udma_dev->func_num - 1; i >= 0; i--) {
		__udma_function_clear(udma_dev, i);
		if (i != 0)
			udma_free_vf_resource(udma_dev, i);
	}
}

static void config_llm_table(struct udma_buf *data_buf, void *cfg_buf)
{
	uint64_t *entry = (uint64_t *)cfg_buf;
@@ -1359,6 +1427,8 @@ static int udma_hw_init(struct udma_dev *udma_dev)

static void udma_hw_exit(struct udma_dev *udma_dev)
{
	udma_function_clear(udma_dev);

	udma_free_link_table(udma_dev);

	put_hem_table(udma_dev);
+11 −0
Original line number Diff line number Diff line
@@ -29,6 +29,11 @@ struct udma_query_fw_info {
	uint32_t rsv[5];
};

struct udma_func_clear {
	uint32_t rst_funcid_en;
	uint32_t func_done;
	uint32_t rsv[4];
};

struct udma_pf_func_info {
	uint32_t own_func_num;
@@ -105,6 +110,11 @@ struct udma_query_oor_cmq {
#define CFG_GLOBAL_PARAM_1US_CYCLES CMQ_REQ_FIELD_LOC(9, 0)
#define CFG_GLOBAL_PARAM_UDP_PORT CMQ_REQ_FIELD_LOC(31, 16)

#define FUNC_CLEAR_RST_FUN_DONE_S 0
#define UDMA_FUNC_CLEAR_TIMEOUT_MSECS	(249 * 2 * 100)
#define UDMA_READ_FUNC_CLEAR_FLAG_INTERVAL	40
#define UDMA_READ_FUNC_CLEAR_FLAG_FAIL_WAIT	20

#define UDMA_FUNC_IRQ_RSV 2
#define UDMA_1US_CFG 999
#define UDMA_EXT_LLM_ENTRY_SZ		8
@@ -204,6 +214,7 @@ enum udma_opcode_type {
	UDMA_OPC_POST_MB				= 0x8504,
	UDMA_OPC_QUERY_MB_ST				= 0x8505,
	UDMA_OPC_CFG_BT_ATTR				= 0x8506,
	UDMA_OPC_FUNC_CLEAR				= 0x8508,
	UDMA_OPC_CLEAR_EXTDB_LIST_INFO			= 0x850d,
	UDMA_OPC_QUERY_VF_RES				= 0x850e,
	UDMA_OPC_CFG_GMV_BT				= 0x8510,