Commit 68b4068d authored by Weibo Zhao's avatar Weibo Zhao Committed by JangShui Yang
Browse files

hns3 udma: fix bugs of code review.

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IAE3IT


CVE: NA

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

Fix bugs of code review for the patch.
Add invalid value check.

Fixes: 40b935d3 ("hns3 udma: support create tp")
Signed-off-by: default avatarWenChun Fei <feiwenchun@huawei.com>
Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent 6afbc2c5
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -601,15 +601,16 @@ int udma_register_udca(struct udma_dev *udma_dev,
{
	struct udma_dca_ctx *dca_ctx = &context->dca_ctx;
	struct hns3_udma_create_ctx_ucmd ucmd = {};
	int max_qps;
	int ret;
	uint32_t max_qps;

	ret = copy_from_user(&ucmd, (void *)udrv_data->in_addr,
			     min_t(uint32_t, udrv_data->in_len,
				   (uint32_t)sizeof(ucmd)));
	if (ret) {
		dev_err(udma_dev->dev, "Failed to copy udata, ret = %d.\n",
			ret);
	if (!udrv_data->in_addr || udrv_data->in_len < sizeof(ucmd)) {
		dev_err(udma_dev->dev, "Invalid udca in_len %u or null addr.\n",
			udrv_data->in_len);
		return -EINVAL;
	}

	if (copy_from_user(&ucmd, (void *)udrv_data->in_addr, sizeof(ucmd))) {
		dev_err(udma_dev->dev, "Failed to copy udata.\n");
		return -EFAULT;
	}

@@ -709,7 +710,7 @@ static int shrink_dca_page_proc(struct dca_mem *mem, uint32_t index,
{
	struct udma_dca_shrink_resp *resp = param;
	struct dca_page_state *state;
	int i, free_pages;
	uint32_t i, free_pages;

	free_pages = 0;
	for (i = 0; i < mem->page_count; i++) {
+16 −8
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ static int stats_dca_qp_proc(struct dca_page_state *states, uint32_t count,
static void dca_ctx_stats_qp(struct udma_dca_ctx *ctx,
			     uintptr_t *qpn_bitmap, uint32_t qpn_max)
{
	struct dca_stats_qp_attr attr;
	struct dca_stats_qp_attr attr = {};

	attr.qpn_bitmap = qpn_bitmap;
	attr.qpn_max = qpn_max;
@@ -125,9 +125,10 @@ static void dca_ctx_stats_qp(struct udma_dca_ctx *ctx,
static uint64_t calc_loading_percent(size_t total, size_t free,
				     uint32_t *out_rem)
{
	uint32_t all_pages, used_pages, free_pages, scale;
	uint64_t all_pages, used_pages, free_pages;
	uint64_t percent = 0;
	uint32_t rem = 0;
	uint32_t scale;

	all_pages = total >> UDMA_HW_PAGE_SHIFT;
	free_pages = free >> UDMA_HW_PAGE_SHIFT;
@@ -165,10 +166,11 @@ static void dca_stats_ctx_qp_in_seqfile(struct udma_dev *udma_dev,
					struct udma_dca_ctx *ctx,
					struct seq_file *file)
{
	struct dca_qp_stats stats;
	uint32_t qpn, nbits;
	struct dca_qp_stats stats = {};
	struct udma_qp *qp;
	uintptr_t *bitmap;
	uint32_t qpn = 0;
	uint32_t nbits;

	nbits = udma_dev->caps.num_qps;
	if (nbits < 1)
@@ -247,7 +249,7 @@ static void init_dca_ctx_debugfs(struct udma_dca_ctx_debugfs *dbgfs,
				 struct udma_dev *udma_dev,
				 struct udma_ucontext *uctx)
{
	char name[DCA_CTX_PID_LEN];
	char name[DCA_CTX_PID_LEN] = {};

	if (IS_ERR_OR_NULL(parent))
		return;
@@ -337,8 +339,10 @@ void udma_register_debugfs(struct udma_dev *udma_dev)
{
	struct udma_dev_debugfs *dbgfs;

	if (IS_ERR_OR_NULL(udma_dbgfs_root))
	if (IS_ERR_OR_NULL(udma_dbgfs_root)) {
		dev_err(udma_dev->dev, "udma_dbgfs_root is NULL.\n");
		return;
	}

	dbgfs = kzalloc(sizeof(*dbgfs), GFP_KERNEL);
	if (!dbgfs)
@@ -362,12 +366,16 @@ void udma_unregister_debugfs(struct udma_dev *udma_dev)
{
	struct udma_dev_debugfs *dbgfs;

	if (IS_ERR_OR_NULL(udma_dbgfs_root))
	if (IS_ERR_OR_NULL(udma_dbgfs_root)) {
		dev_err(udma_dev->dev, "udma_dbgfs_root is NULL.\n");
		return;
	}

	dbgfs = udma_dev->dbgfs;
	if (!dbgfs)
	if (!dbgfs) {
		dev_err(udma_dev->dev, "dbgfs is NULL.\n");
		return;
	}

	udma_dev->dbgfs = NULL;

+23 −10
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ static int udma_dfx_read_buf(char *str, const char *buf)
		str_buf++;
		blk_cnt++;
	}
	while (str_buf[cnt] != ' ' && str_buf[cnt] != '\0' &&
	       cnt < UDMA_DFX_STR_LEN_MAX - 1)
	while ((cnt < (UDMA_DFX_STR_LEN_MAX - 1)) && (str_buf[cnt] != ' ') &&
		(str_buf[cnt] != '\0'))
		cnt++;

	if (((uint32_t)(blk_cnt + cnt) < strlen(buf)) || str_buf[cnt] != '\0')
@@ -106,6 +106,7 @@ static void udma_dfx_seg_print(struct udma_dev *udma_dev, uint32_t seg_key,
static int udma_dfx_seg_store(const char *p_buf, struct udma_dfx_info *udma_dfx)
{
	struct udma_dev *udma_dev = (struct udma_dev *)udma_dfx->priv;
	struct udma_ida *seg_ida = &udma_dev->seg_table.seg_ida;
	struct udma_mpt_entry mpt_entry;
	char str[UDMA_DFX_STR_LEN_MAX];
	uint32_t mpt_index;
@@ -123,7 +124,12 @@ static int udma_dfx_seg_store(const char *p_buf, struct udma_dfx_info *udma_dfx)
		return -EINVAL;
	}

	mpt_index = key_to_hw_index(seg_key) & (udma_dev->caps.num_mtpts - 1);
	mpt_index = key_to_hw_index(seg_key);
	if (mpt_index > seg_ida->max) {
		dev_err(udma_dev->dev, "seg_key(%u) is invalid.\n", seg_key);
		return -EINVAL;
	}

	ret = udma_dfx_query_context(udma_dev, mpt_index, &mpt_entry,
				     sizeof(mpt_entry), UDMA_CMD_QUERY_MPT);
	if (ret) {
@@ -836,16 +842,22 @@ static int udma_query_res_seg(struct udma_dev *udma_dev, struct ubcore_res_key *
			      struct ubcore_res_val *val)
{
	struct ubcore_res_seg_val *seg = (struct ubcore_res_seg_val *)val->addr;
	struct udma_ida *seg_ida = &udma_dev->seg_table.seg_ida;
	struct udma_mpt_entry mpt_entry;
	uint32_t mpt_index, token_id;
	union ubcore_eid eid = {};
	struct seg_list *seg_now;
	union ubcore_eid eid;
	int ret, i;

	if (key->key_cnt == 0)
		return udma_query_res_seg_list(udma_dev, key, val);

	mpt_index = key_to_hw_index(key->key) & (udma_dev->caps.num_mtpts - 1);
	mpt_index = key_to_hw_index(key->key);
	if (mpt_index > seg_ida->max) {
		dev_err(udma_dev->dev, "seg_key(%u) is invalid.\n", key->key);
		return -EINVAL;
	}

	ret = udma_dfx_query_context(udma_dev, mpt_index, &mpt_entry,
				     sizeof(mpt_entry), UDMA_CMD_QUERY_MPT);
	if (ret) {
@@ -979,10 +991,9 @@ int udma_query_res(struct ubcore_device *dev,
		return udma_query_res_dev_tp(udma_dev, key, val);
	default:
		dev_err(udma_dev->dev, "key type: %u invalid.\n", (uint32_t)key->type);
		return -EINVAL;
	}

	return 0;
	return -EINVAL;
}

UDMA_DFX_FILE_ATTR_DEF(tp_context, NULL, udma_dfx_tp_store);
@@ -1185,12 +1196,15 @@ static int udma_dfx_add_udma_device(struct udma_dev *udma_dev)
	if (udma_dev_count == MAX_UDMA_DEV) {
		dev_err(drv_device,
			"udma dfx add device failed, g_udma_dfx_list is full.\n.");
		ret = -EINVAL;
		goto g_udma_dfx_list_full;
		return -EINVAL;
	}
	for (i = 0; i < MAX_UDMA_DEV; i++)
		if (!g_udma_dfx_list[i].dfx)
			break;
	if (i == MAX_UDMA_DEV) {
		dev_err(drv_device, "no free udma dfx list.\n.");
		return -EINVAL;
	}

	g_udma_dfx_list[i].dev = udma_dev;
	g_udma_dfx_list[i].dfx = kzalloc(sizeof(struct udma_dfx_info),
@@ -1230,7 +1244,6 @@ static int udma_dfx_add_udma_device(struct udma_dev *udma_dev)
	g_udma_dfx_list[i].dfx = NULL;
dfx_info_alloc_failed:
	g_udma_dfx_list[i].dev = NULL;
g_udma_dfx_list_full:
	return ret;
}

+5 −5
Original line number Diff line number Diff line
@@ -21,9 +21,9 @@ static int config_gmv_table(struct udma_dev *udma_dev, struct udma_eid *udma_eid
			    uint32_t eid_index)
{
	enum udma_sgid_type sgid_type = udma_eid->type;
	struct udma_cmq_desc desc[UDMA_CMQ_DESC_SIZE];
	struct udma_cfg_gmv_tb_a *tb_a;
	struct udma_cfg_gmv_tb_b *tb_b;
	struct udma_cmq_desc desc[2];
	uint16_t guid_shift = 0;
	uint16_t smac_l;

@@ -95,8 +95,8 @@ static int add_eid_entry(struct udma_dev *udma_dev, union ubcore_eid eid,
err_store:
	local_ret = clear_gmv_table(udma_dev, eid_index);
	if (local_ret)
		dev_err(udma_dev->dev,
			"Failed to clear eid from GMV table, ret = %d.\n", local_ret);
		dev_err(udma_dev->dev, "Failed to clear eid from GMV table, ret = %d.\n",
			local_ret);
err_config:
	kfree(udma_eid);
	return ret;
@@ -166,9 +166,9 @@ int udma_delete_ueid(struct ubcore_device *dev, uint16_t fe_idx,

int udma_find_eid_idx(struct udma_dev *dev, union ubcore_eid eid)
{
	struct udma_eid *udma_eid;
	struct udma_eid *udma_eid = NULL;
	int eid_index = -EINVAL;
	unsigned long index;
	unsigned long index = 0;

	xa_lock(&dev->eid_table);
	xa_for_each(&dev->eid_table, index, udma_eid) {
+49 −42
Original line number Diff line number Diff line
@@ -14,12 +14,12 @@
 */

#include <linux/acpi.h>
#include "urma/ubcore_uapi.h"
#include "hnae3.h"
#include "hns3_udma_hem.h"
#include "hns3_udma_device.h"
#include "hns3_udma_db.h"
#include "hns3_udma_jfc.h"
#include "hns3_udma_jfr.h"
#include "hns3_udma_qp.h"
#include "hns3_udma_eq.h"

static int alloc_eq_buf(struct udma_dev *udma_dev, struct udma_eq *eq)
@@ -130,17 +130,31 @@ static int udma_create_eq(struct udma_dev *udma_dev, struct udma_eq *eq,
	if (IS_ERR(mailbox))
		return -ENOMEM;

	ret = config_eqc(udma_dev, eq, mailbox->buf);
	if (ret)
	ret = alloc_eq_buf(udma_dev, eq);
	if (ret) {
		dev_err(udma_dev->dev, "failed to alloc eq buf.\n");
		goto err_cmd_mbox;
	}
	ret = config_eqc(udma_dev, eq, mailbox->buf);
	if (ret) {
		dev_err(udma_dev->dev, "[mailbox cmd] config eqc failed.\n");
		goto err_eq_buf;
	}

	mb = (struct udma_mbox *)desc.data;
	udma_cmq_setup_basic_desc(&desc, UDMA_OPC_POST_MB, false);
	mbox_desc_init(mb, mailbox->dma, 0, eq->eqn, eq_cmd);
	ret = udma_cmd_mbox(udma_dev, &desc, UDMA_CMD_TIMEOUT_MSECS, 0);
	if (ret)
	if (ret) {
		dev_err(udma_dev->dev, "[mailbox cmd] create eqc failed.\n");
		goto err_eq_buf;
	}

	udma_free_cmd_mailbox(udma_dev, mailbox);
	return 0;

err_eq_buf:
	free_eq_buf(udma_dev, eq);
err_cmd_mbox:
	udma_free_cmd_mailbox(udma_dev, mailbox);

@@ -210,9 +224,10 @@ static void aeq_event_report(struct udma_dev *udma_dev,
				  UDMA_AEQE_SUB_TYPE_M,
				  UDMA_AEQE_SUB_TYPE_S);
	if (event_type != UDMA_EVENT_TYPE_COMM_EST)
		dev_err(udma_dev->dev,
			"print AEQE: 0x%x, 0x%x queue:0x%x event_type:0x%x, sub_type:0x%x\n",
			*tmp, *(tmp + 1), queue_num, event_type, sub_type);
		dev_err(udma_dev->dev, "print AEQE: 0x%x, 0x%x; "
			"queue:0x%x event_type:0x%x, sub_type:0x%x\n",
			*tmp, *(tmp + 1), queue_num, event_type,
			sub_type);

	switch (event_type) {
	case UDMA_EVENT_TYPE_COMM_EST:
@@ -734,6 +749,29 @@ static void set_jfae_attr(struct udma_dev *udma_dev, struct udma_eq *eq,
	eq->eq_period = UDMA_AEQ_DEFAULT_INTERVAL;
}

static void udma_destroy_eq(struct udma_dev *udma_dev, struct udma_eq *eq)
{
	struct device *dev = udma_dev->dev;
	struct udma_cmq_desc desc;
	struct udma_mbox *mb;
	int eqn = eq->eqn;
	uint16_t eq_cmd;
	int ret;

	mb = (struct udma_mbox *)desc.data;
	udma_cmq_setup_basic_desc(&desc, UDMA_OPC_POST_MB, false);
	if (eqn < udma_dev->caps.num_comp_vectors)
		eq_cmd = UDMA_CMD_DESTROY_CEQC;
	else
		eq_cmd = UDMA_CMD_DESTROY_AEQC;
	mbox_desc_init(mb, 0, 0, eqn & UDMA_EQN_M, eq_cmd);

	ret = udma_cmd_mbox(udma_dev, &desc, UDMA_CMD_TIMEOUT_MSECS, 0);
	if (ret)
		dev_err(dev, "[mailbox cmd] destroy eqc(%d) failed.\n", eqn);
	free_eq_buf(udma_dev, eq);
}

static int udma_create_hw_eq(struct udma_dev *udma_dev, int ceq_num,
			     int aeq_num, int other_num)
{
@@ -760,16 +798,9 @@ static int udma_create_hw_eq(struct udma_dev *udma_dev, int ceq_num,
			set_jfae_attr(udma_dev, eq, (i - ceq_num + other_num));
		}
		init_eq_config(udma_dev, eq);
		ret = alloc_eq_buf(udma_dev, eq);
		if (ret) {
			dev_err(udma_dev->dev, "failed to alloc eq buf.\n");
			goto err_out;
		}

		ret = udma_create_eq(udma_dev, eq, eq_cmd);
		if (ret) {
			dev_err(udma_dev->dev, "failed to create eq.\n");
			free_eq_buf(udma_dev, &eq_table->eq[i]);
			goto err_out;
		}
	}
@@ -778,28 +809,11 @@ static int udma_create_hw_eq(struct udma_dev *udma_dev, int ceq_num,

err_out:
	for (i -= 1; i >= 0; i--)
		free_eq_buf(udma_dev, &eq_table->eq[i]);
		udma_destroy_eq(udma_dev, &eq_table->eq[i]);

	return ret;
}

void udma_destroy_eqc(struct udma_dev *udma_dev, int eqn, uint32_t eq_cmd)
{
	struct device *dev = udma_dev->dev;
	struct udma_cmq_desc desc;
	struct udma_mbox *mb;
	int ret;

	mb = (struct udma_mbox *)desc.data;
	udma_cmq_setup_basic_desc(&desc, UDMA_OPC_POST_MB, false);

	mbox_desc_init(mb, 0, 0, eqn & UDMA_EQN_M, eq_cmd);

	ret = udma_cmd_mbox(udma_dev, &desc, UDMA_CMD_TIMEOUT_MSECS, 0);
	if (ret)
		dev_err(dev, "[mailbox cmd] destroy eqc(%d) failed.\n", eqn);
}

static void __udma_free_irq(struct udma_dev *udma_dev)
{
	int irq_num;
@@ -824,7 +838,6 @@ static void __udma_free_irq(struct udma_dev *udma_dev)
void udma_cleanup_eq_table(struct udma_dev *udma_dev)
{
	struct udma_eq_table *eq_table = &udma_dev->eq_table;
	uint32_t eq_cmd;
	int eq_num;
	int i;

@@ -839,13 +852,7 @@ void udma_cleanup_eq_table(struct udma_dev *udma_dev)
	destroy_workqueue(udma_dev->irq_workq);

	for (i = 0; i < eq_num; i++) {
		if (i < udma_dev->caps.num_comp_vectors)
			eq_cmd = UDMA_CMD_DESTROY_CEQC;
		else
			eq_cmd = UDMA_CMD_DESTROY_AEQC;

		udma_destroy_eqc(udma_dev, i, eq_cmd);
		free_eq_buf(udma_dev, &eq_table->eq[i]);
		udma_destroy_eq(udma_dev, &eq_table->eq[i]);
	}

	kfree(eq_table->eq);
@@ -903,7 +910,7 @@ int udma_init_eq_table(struct udma_dev *udma_dev)

err_alloc_workqueue_fail:
	for (i = ceq_num + aeq_num - 1; i >= 0; i--)
		free_eq_buf(udma_dev, &eq_table->eq[i]);
		udma_destroy_eq(udma_dev, &eq_table->eq[i]);

err_create_eq_fail:
	kfree(eq_table->eq);
Loading