Commit 881f2a14 authored by Weibo Zhao's avatar Weibo Zhao Committed by JangShui Yang
Browse files

hns3 udma: add verify udata and in/out addr.

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


CVE: NA

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

Add verify udata and in/out addr for the patch.
Fix bugs of hem create.

Fixes: b330adf6 (hns3 udma: function of hardware init)
Signed-off-by: default avatarWenChun Fei <feiwenchun@huawei.com>
Signed-off-by: default avatarWeibo Zhao <zhaoweibo3@huawei.com>
parent 68b4068d
Loading
Loading
Loading
Loading
+204 −205
Original line number Diff line number Diff line
@@ -98,6 +98,15 @@ static int udma_get_bt_num(uint32_t table_type, uint32_t hop_num)
		return 0;
}

static void set_mhop_field_info(struct udma_hem_mhop *mhop, uint32_t buf_sz,
				uint32_t bt_sz, uint32_t ba_num, uint32_t hop_num)
{
	mhop->buf_chunk_size = 1U << (buf_sz + PAGE_SHIFT);
	mhop->bt_chunk_size = 1U << (bt_sz + PAGE_SHIFT);
	mhop->ba_l0_num = ba_num;
	mhop->hop_num = hop_num;
}

static int get_hem_table_config(struct udma_dev *udma_dev,
				struct udma_hem_mhop *mhop,
				uint32_t type)
@@ -106,72 +115,45 @@ static int get_hem_table_config(struct udma_dev *udma_dev,

	switch (type) {
	case HEM_TYPE_QPC:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.qpc_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.qpc_ba_pg_sz
					     + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.qpc_bt_num;
		mhop->hop_num = udma_dev->caps.qpc_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.qpc_buf_pg_sz, udma_dev->caps.qpc_ba_pg_sz,
				    udma_dev->caps.qpc_bt_num, udma_dev->caps.qpc_hop_num);
		break;
	case HEM_TYPE_MTPT:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.mpt_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.mpt_ba_pg_sz
					     + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.mpt_bt_num;
		mhop->hop_num = udma_dev->caps.mpt_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.mpt_buf_pg_sz, udma_dev->caps.mpt_ba_pg_sz,
				    udma_dev->caps.mpt_bt_num, udma_dev->caps.mpt_hop_num);
		break;
	case HEM_TYPE_CQC:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.cqc_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.cqc_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.cqc_bt_num;
		mhop->hop_num = udma_dev->caps.cqc_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.cqc_buf_pg_sz, udma_dev->caps.cqc_ba_pg_sz,
				    udma_dev->caps.cqc_bt_num, udma_dev->caps.cqc_hop_num);
		break;
	case HEM_TYPE_SCCC:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.sccc_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.sccc_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.sccc_bt_num;
		mhop->hop_num = udma_dev->caps.sccc_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.sccc_buf_pg_sz,
				    udma_dev->caps.sccc_ba_pg_sz, udma_dev->caps.sccc_bt_num,
				    udma_dev->caps.sccc_hop_num);
		break;
	case HEM_TYPE_QPC_TIMER:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.qpc_timer_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.qpc_timer_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.qpc_timer_bt_num;
		mhop->hop_num = udma_dev->caps.qpc_timer_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.qpc_timer_buf_pg_sz,
				    udma_dev->caps.qpc_timer_ba_pg_sz,
				    udma_dev->caps.qpc_timer_bt_num,
				    udma_dev->caps.qpc_timer_hop_num);
		break;
	case HEM_TYPE_CQC_TIMER:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.cqc_timer_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.cqc_timer_ba_pg_sz
					    + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.cqc_timer_bt_num;
		mhop->hop_num = udma_dev->caps.cqc_timer_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.cqc_timer_buf_pg_sz,
				    udma_dev->caps.cqc_timer_ba_pg_sz,
				    udma_dev->caps.cqc_timer_bt_num,
				    udma_dev->caps.cqc_timer_hop_num);
		break;
	case HEM_TYPE_SRQC:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.srqc_buf_pg_sz
					     + PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.srqc_ba_pg_sz
					     + PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.srqc_bt_num;
		mhop->hop_num = udma_dev->caps.srqc_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.srqc_buf_pg_sz,
				    udma_dev->caps.srqc_ba_pg_sz, udma_dev->caps.srqc_bt_num,
				    udma_dev->caps.srqc_hop_num);
		break;
	case HEM_TYPE_GMV:
		mhop->buf_chunk_size = 1U << (udma_dev->caps.gmv_buf_pg_sz +
					     PAGE_SHIFT);
		mhop->bt_chunk_size = 1U << (udma_dev->caps.gmv_ba_pg_sz +
					    PAGE_SHIFT);
		mhop->ba_l0_num = udma_dev->caps.gmv_bt_num;
		mhop->hop_num = udma_dev->caps.gmv_hop_num;
		set_mhop_field_info(mhop, udma_dev->caps.gmv_buf_pg_sz, udma_dev->caps.gmv_ba_pg_sz,
				    udma_dev->caps.gmv_bt_num, udma_dev->caps.gmv_hop_num);
		break;
	default:
		dev_err(dev, "table %u not support multi-hop addressing!\n",
			type);
		dev_err(dev, "table %u not support multi-hop addressing!\n", type);
		return -EINVAL;
	}

@@ -204,6 +186,13 @@ int udma_calc_hem_mhop(struct udma_dev *udma_dev,
	chunk_ba_num = mhop->bt_chunk_size / BA_BYTE_LEN;
	chunk_size = table->type < HEM_TYPE_MTT ? mhop->buf_chunk_size :
			      mhop->bt_chunk_size;

	if (table->obj_size == 0 || table->obj_size > chunk_size) {
		dev_err(dev, "obj size is wrong, obj_size = %llu, chunk_size = %d.\n",
			table->obj_size, chunk_size);
		return -EINVAL;
	}

	table_idx = *obj / (chunk_size / table->obj_size);
	switch (bt_num) {
	case 3:
@@ -223,7 +212,7 @@ int udma_calc_hem_mhop(struct udma_dev *udma_dev,
			table->type, mhop->hop_num);
		return -EINVAL;
	}
	if (mhop->l0_idx >= mhop->ba_l0_num)
	if (mhop->l0_idx >= mhop->ba_l0_num && mhop->ba_l0_num != 0)
		mhop->l0_idx %= mhop->ba_l0_num;

	return 0;
@@ -377,18 +366,13 @@ static void free_mhop_hem(struct udma_dev *udma_dev,
	}
}

static int alloc_mhop_hem(struct udma_dev *udma_dev,
static int udma_alloc_table_btl0(struct udma_dev *udma_dev,
				 struct udma_hem_table *table,
				 struct udma_hem_mhop *mhop,
				 struct udma_hem_index *index)
{
	uint32_t bt_size = mhop->bt_chunk_size;
	struct device *dev = udma_dev->dev;
	struct udma_hem_iter iter;
	uint64_t bt_ba;
	uint32_t size;
	gfp_t flag;
	int ret;

	/* alloc L1 BA's chunk */
	if ((check_whether_bt_num_3(table->type, mhop->hop_num) ||
@@ -397,28 +381,60 @@ static int alloc_mhop_hem(struct udma_dev *udma_dev,
		table->bt_l0[index->l0] = dma_alloc_coherent(dev, bt_size,
					  &table->bt_l0_dma_addr[index->l0],
					  GFP_KERNEL);
		if (!table->bt_l0[index->l0]) {
			ret = -ENOMEM;
			goto out;
		}
		if (!table->bt_l0[index->l0])
			return -ENOMEM;

		index->inited |= HEM_INDEX_L0;
	}

	return 0;
}

static int udma_alloc_table_btl1(struct udma_dev *udma_dev,
				 struct udma_hem_table *table,
				 struct udma_hem_mhop *mhop,
				 struct udma_hem_index *index)
{
	uint32_t bt_size = mhop->bt_chunk_size;
	struct device *dev = udma_dev->dev;

	/* alloc L2 BA's chunk */
	if (check_whether_bt_num_3(table->type, mhop->hop_num) &&
	    !table->bt_l1[index->l1])  {
		table->bt_l1[index->l1] = dma_alloc_coherent(dev, bt_size,
					  &table->bt_l1_dma_addr[index->l1],
					  GFP_KERNEL);
		if (!table->bt_l1[index->l1]) {
			ret = -ENOMEM;
			goto err_alloc_hem;
		}
		if (!table->bt_l1[index->l1])
			return -ENOMEM;

		index->inited |= HEM_INDEX_L1;
		*(table->bt_l0[index->l0] + mhop->l1_idx) =
					       table->bt_l1_dma_addr[index->l1];
	}

	return 0;
}

static int alloc_mhop_hem(struct udma_dev *udma_dev,
			  struct udma_hem_table *table,
			  struct udma_hem_mhop *mhop,
			  struct udma_hem_index *index)
{
	uint32_t bt_size = mhop->bt_chunk_size;
	struct udma_hem_iter iter;
	uint64_t bt_ba;
	uint32_t size;
	gfp_t flag;
	int ret;

	ret = udma_alloc_table_btl0(udma_dev, table, mhop, index);
	if (ret)
		goto out;

	ret = udma_alloc_table_btl1(udma_dev, table, mhop, index);
	if (ret)
		goto err_alloc_hem;

	/*
	 * alloc buffer space chunk for QPC/MTPT/CQC/SRQC/SCCC.
	 * alloc bt space chunk for MTT/CQE.
@@ -545,6 +561,12 @@ int udma_table_get(struct udma_dev *udma_dev,
	if (udma_check_whether_mhop(udma_dev, table->type))
		return udma_table_mhop_get(udma_dev, table, obj);

	if (table->obj_size == 0 || table->obj_size > table->table_chunk_size) {
		dev_err(dev, "obj size is wrong, obj_size = %llu, chunk_size = %llu.\n",
			table->obj_size, table->table_chunk_size);
		return -EINVAL;
	}

	i = obj / (table->table_chunk_size / table->obj_size);

	mutex_lock(&table->mutex);
@@ -661,6 +683,12 @@ void udma_table_put(struct udma_dev *udma_dev,
		return;
	}

	if (table->obj_size == 0 || table->obj_size > table->table_chunk_size) {
		dev_err(dev, "obj size is wrong, obj_size = %llu, chunk_size = %llu.\n",
			table->obj_size, table->table_chunk_size);
		return;
	}

	i = obj / (table->table_chunk_size / table->obj_size);

	if (!refcount_dec_and_mutex_lock(&table->hem[i]->refcount,
@@ -676,73 +704,72 @@ void udma_table_put(struct udma_dev *udma_dev,
	mutex_unlock(&table->mutex);
}

void *udma_table_find(struct udma_dev *udma_dev,
		      struct udma_hem_table *table,
		      uint64_t obj, dma_addr_t *dma_handle)
static void udma_free_hem_table(struct udma_hem_table *table)
{
	struct udma_hem_chunk *chunk;
	struct udma_hem_mhop mhop;
	uint64_t mhop_obj = obj;
	uint64_t obj_per_chunk;
	int offset, dma_offset;
	struct udma_hem *hem;
	uint32_t hem_idx = 0;
	uint64_t idx_offset;
	void *addr = NULL;
	uint32_t length;
	uint32_t i, j;

	mutex_lock(&table->mutex);
	kfree(table->hem);
	table->hem = NULL;
}

	if (!udma_check_whether_mhop(udma_dev, table->type)) {
		obj_per_chunk = table->table_chunk_size / table->obj_size;
		hem = table->hem[obj / obj_per_chunk];
		idx_offset = obj % obj_per_chunk;
		dma_offset = offset = idx_offset * table->obj_size;
	} else {
		/* 8 bytes per BA and 8 BA per segment */
		uint32_t seg_size = 64;
static void udma_free_hem_btl0(struct udma_hem_table *table)
{
	kfree(table->bt_l0);
	table->bt_l0 = NULL;
}

		if (udma_calc_hem_mhop(udma_dev, table, &mhop_obj, &mhop))
			goto out;
		/* mtt mhop */
		i = mhop.l0_idx;
		j = mhop.l1_idx;
		if (mhop.hop_num == 2)
			hem_idx = i * (mhop.bt_chunk_size / BA_BYTE_LEN) + j;
		else if (mhop.hop_num == 1 ||
			 mhop.hop_num == UDMA_HOP_NUM_0)
			hem_idx = i;
static void udma_free_hem_btl1(struct udma_hem_table *table)
{
	kfree(table->bt_l1);
	table->bt_l1 = NULL;
}

		hem = table->hem[hem_idx];
		dma_offset = offset = obj * seg_size % mhop.bt_chunk_size;
		if (mhop.hop_num == 2)
			dma_offset = offset = 0;
static void udma_free_hem_btl1_dma_addr(struct udma_hem_table *table)
{
	kfree(table->bt_l1_dma_addr);
	table->bt_l1_dma_addr = NULL;
}

	if (!hem)
		goto out;
static int check_whether_mhop_bt2(struct udma_hem_table *table, uint32_t type,
				  uint32_t hop_num, uint64_t num_bt_l0)
{
	if (check_whether_bt_num_2(type, hop_num) ||
	    check_whether_bt_num_3(type, hop_num)) {
		table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0), GFP_KERNEL);
		if (!table->bt_l0)
			return -ENOMEM;

	list_for_each_entry(chunk, &hem->chunk_list, list) {
		for (i = 0; (int)i < chunk->npages; ++i) {
			length = sg_dma_len(&chunk->mem[i]);
			if (dma_handle && dma_offset >= 0) {
				*dma_handle = length > (uint32_t)dma_offset ? sg_dma_address(
						&chunk->mem[i]) + dma_offset : *dma_handle;
				dma_offset -= length;
		table->bt_l0_dma_addr = kcalloc(num_bt_l0,
					sizeof(*table->bt_l0_dma_addr),
					GFP_KERNEL);
		if (!table->bt_l0_dma_addr) {
			udma_free_hem_btl0(table);
			return -ENOMEM;
		}
	}

			if (length > (uint32_t)offset) {
				addr = (char *)chunk->buf[i] + offset;
				goto out;
	return 0;
}
			offset -= length;

static int check_whether_mhop_bt3(struct udma_hem_table *table, uint32_t type,
				  uint32_t hop_num, uint64_t bt_chunk_num, uint64_t num_hem)
{
	uint64_t num_bt_l1;

	if (check_whether_bt_num_3(type, hop_num)) {
		num_bt_l1 = DIV_ROUND_UP(num_hem, bt_chunk_num);
		table->bt_l1 = kcalloc(num_bt_l1, sizeof(*table->bt_l1), GFP_KERNEL);
		if (!table->bt_l1)
			return -ENOMEM;

		table->bt_l1_dma_addr = kcalloc(num_bt_l1,
					sizeof(*table->bt_l1_dma_addr), GFP_KERNEL);

		if (!table->bt_l1_dma_addr) {
			udma_free_hem_btl1(table);
			return -ENOMEM;
		}
	}

out:
	mutex_unlock(&table->mutex);
	return addr;
	return 0;
}

int udma_init_hem_table(struct udma_dev *udma_dev,
@@ -752,22 +779,23 @@ int udma_init_hem_table(struct udma_dev *udma_dev,
	uint64_t obj_per_chunk;
	uint64_t num_hem;

	if (obj_size == 0) {
		dev_err(udma_dev->dev, "obj size is zero.\n");
		return -EINVAL;
	}

	if (!udma_check_whether_mhop(udma_dev, type)) {
		table->table_chunk_size = udma_dev->caps.chunk_sz;
		obj_per_chunk = table->table_chunk_size / obj_size;
		num_hem = DIV_ROUND_UP(nobj, obj_per_chunk);

		table->hem = kcalloc(num_hem, sizeof(*table->hem),
							 GFP_KERNEL);
		table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
		if (!table->hem)
			return -ENOMEM;
	} else {
		struct udma_hem_mhop mhop = {};
		uint64_t buf_chunk_size;
		uint64_t bt_chunk_size;
		uint64_t bt_chunk_num;
		uint64_t num_bt_l0;
		uint32_t hop_num;
		uint64_t buf_chunk_size, bt_chunk_size, bt_chunk_num;
		uint64_t num_bt_l0, hop_num;
		int ret;

		ret = get_hem_table_config(udma_dev, &mhop, type);
@@ -786,40 +814,22 @@ int udma_init_hem_table(struct udma_dev *udma_dev,
		if (type >= HEM_TYPE_MTT)
			num_bt_l0 = bt_chunk_num;

		table->hem = kcalloc(num_hem, sizeof(*table->hem),
							 GFP_KERNEL);
		table->hem = kcalloc(num_hem, sizeof(*table->hem), GFP_KERNEL);
		if (!table->hem)
			goto err_kcalloc_hem_buf;

		if (check_whether_bt_num_3(type, hop_num)) {
			uint64_t num_bt_l1;

			num_bt_l1 = DIV_ROUND_UP(num_hem, bt_chunk_num);
			table->bt_l1 = kcalloc(num_bt_l1, sizeof(*table->bt_l1),
					       GFP_KERNEL);
			if (!table->bt_l1)
				goto err_kcalloc_bt_l1;

			table->bt_l1_dma_addr = kcalloc(num_bt_l1,
						 sizeof(*table->bt_l1_dma_addr),
						 GFP_KERNEL);
			return -ENOMEM;

			if (!table->bt_l1_dma_addr)
				goto err_kcalloc_l1_dma;
		if (check_whether_mhop_bt3(table, type, hop_num, bt_chunk_num, num_hem)) {
			udma_free_hem_table(table);
			dev_err(udma_dev->dev, "failed to alloc table bt_l1.\n");
			return -ENOMEM;
		}

		if (check_whether_bt_num_2(type, hop_num) ||
		    check_whether_bt_num_3(type, hop_num)) {
			table->bt_l0 = kcalloc(num_bt_l0, sizeof(*table->bt_l0),
						       GFP_KERNEL);
			if (!table->bt_l0)
				goto err_kcalloc_bt_l0;

			table->bt_l0_dma_addr = kcalloc(num_bt_l0,
						 sizeof(*table->bt_l0_dma_addr),
						 GFP_KERNEL);
			if (!table->bt_l0_dma_addr)
				goto err_kcalloc_l0_dma;
		if (check_whether_mhop_bt2(table, type, hop_num, num_bt_l0)) {
			udma_free_hem_btl1_dma_addr(table);
			udma_free_hem_btl1(table);
			udma_free_hem_table(table);
			dev_err(udma_dev->dev, "failed to alloc table bt_l0.\n");
			return -ENOMEM;
		}
	}

@@ -829,25 +839,6 @@ int udma_init_hem_table(struct udma_dev *udma_dev,
	mutex_init(&table->mutex);

	return 0;

err_kcalloc_l0_dma:
	kfree(table->bt_l0);
	table->bt_l0 = NULL;

err_kcalloc_bt_l0:
	kfree(table->bt_l1_dma_addr);
	table->bt_l1_dma_addr = NULL;

err_kcalloc_l1_dma:
	kfree(table->bt_l1);
	table->bt_l1 = NULL;

err_kcalloc_bt_l1:
	kfree(table->hem);
	table->hem = NULL;

err_kcalloc_hem_buf:
	return -ENOMEM;
}

static void udma_cleanup_mhop_hem_table(struct udma_dev *udma_dev,
@@ -887,6 +878,11 @@ void udma_cleanup_hem_table(struct udma_dev *udma_dev,
	struct device *dev = udma_dev->dev;
	uint64_t i;

	if (table->obj_size == 0) {
		dev_err(udma_dev->dev, "obj size is zero.\n");
		return;
	}

	if (udma_check_whether_mhop(udma_dev, table->type)) {
		udma_cleanup_mhop_hem_table(udma_dev, table);
		return;
@@ -1065,28 +1061,15 @@ static int udma_hem_list_calc_root_ba(const struct udma_buf_region *regions,
	return total;
}

static int hem_list_alloc_mid_bt(struct udma_dev *udma_dev,
				 const struct udma_buf_region *r, int unit,
				 uint32_t offset, struct list_head *mid_bt,
				 struct list_head *btm_bt)
static int hem_list_check_parameter(struct udma_dev *udma_dev,
				    const struct udma_buf_region *r,
				    uint32_t offset)
{
	struct udma_hem_item *hem_ptrs[UDMA_MAX_BT_LEVEL] = { NULL };
	struct list_head temp_list[UDMA_MAX_BT_LEVEL];
	struct udma_hem_item *cur, *pre;
	const int hopnum = r->hopnum;
	int start_aligned;
	uint32_t step;
	int distance;
	int ret = 0;
	int max_ofs;
	int level;
	int end;

	if (hopnum <= 1)
	if (r->hopnum <= 1)
		return 0;

	if (hopnum > UDMA_MAX_BT_LEVEL) {
		dev_err(udma_dev->dev, "invalid hopnum %d!\n", hopnum);
	if (r->hopnum > UDMA_MAX_BT_LEVEL) {
		dev_err(udma_dev->dev, "invalid hopnum %d!\n", r->hopnum);
		return -EINVAL;
	}

@@ -1096,6 +1079,25 @@ static int hem_list_alloc_mid_bt(struct udma_dev *udma_dev,
		return -EINVAL;
	}

	return 0;
}

static int hem_list_alloc_mid_bt(struct udma_dev *udma_dev,
				 const struct udma_buf_region *r, int unit,
				 uint32_t offset, struct list_head *mid_bt,
				 struct list_head *btm_bt)
{
	struct udma_hem_item *hem_ptrs[UDMA_MAX_BT_LEVEL] = { NULL };
	int start_aligned, distance, max_ofs, level, end;
	struct list_head temp_list[UDMA_MAX_BT_LEVEL];
	struct udma_hem_item *cur, *pre;
	const int hopnum = r->hopnum;
	int ret = -EINVAL;
	uint32_t step;

	if (hem_list_check_parameter(udma_dev, r, offset))
		return ret;

	distance = offset - r->offset;
	max_ofs = r->offset + r->count - 1;
	for (level = 0; level < hopnum; level++)
@@ -1110,19 +1112,17 @@ static int hem_list_alloc_mid_bt(struct udma_dev *udma_dev,
		}

		step = hem_list_calc_ba_range(hopnum, level, unit);
		if (step < 1) {
			ret = -EINVAL;
		if (step < 1)
			goto err_exit;
		}

		start_aligned = (distance / step) * step + r->offset;
		end = min_t(int, start_aligned + step - 1, max_ofs);
		cur = hem_list_alloc_item(udma_dev, start_aligned, end, unit,
					  true);
		cur = hem_list_alloc_item(udma_dev, start_aligned, end, unit, true);
		if (!cur) {
			ret = -ENOMEM;
			goto err_exit;
		}

		hem_ptrs[level] = cur;
		list_add(&cur->list, &temp_list[level]);
		if (hem_list_is_bottom_bt(hopnum, level))
@@ -1132,8 +1132,7 @@ static int hem_list_alloc_mid_bt(struct udma_dev *udma_dev,
		if (level > 1) {
			pre = hem_ptrs[level - 1];
			step = (cur->start - pre->start) / step * BA_BYTE_LEN;
			hem_list_link_bt(udma_dev, (char *)pre->addr + step,
					 cur->dma_addr);
			hem_list_link_bt(udma_dev, (char *)pre->addr + step, cur->dma_addr);
		}
	}

+0 −3
Original line number Diff line number Diff line
@@ -128,9 +128,6 @@ int udma_table_get(struct udma_dev *udma_dev,
		   struct udma_hem_table *table, uint64_t obj);
void udma_table_put(struct udma_dev *udma_dev,
		    struct udma_hem_table *table, uint64_t obj);
void *udma_table_find(struct udma_dev *udma_dev,
		      struct udma_hem_table *table, uint64_t obj,
		      dma_addr_t *dma_handle);
int udma_init_hem_table(struct udma_dev *udma_dev,
			struct udma_hem_table *table, uint32_t type,
			uint64_t obj_size, uint64_t nobj);
+46 −27
Original line number Diff line number Diff line
@@ -126,18 +126,27 @@ static int check_create_jfc(struct udma_dev *udma_dev,
			    struct hns3_udma_create_jfc_ucmd *ucmd,
			    struct ubcore_udata *udata)
{
	unsigned long byte;
	int ret;

	if (udata) {
		ret = copy_from_user((void *)ucmd,
				     (void *)udata->udrv_data->in_addr,
				     min_t(uint32_t, udata->udrv_data->in_len,
					   (uint32_t)sizeof(struct hns3_udma_create_jfc_ucmd)));
		if (ret) {
			dev_err(udma_dev->dev,
				"failed to copy JFC udata, ret = %d.\n", ret);
			return ret;
	if (!udata || !udata->udrv_data) {
		dev_err(udma_dev->dev, "jfc udata or udrv_data is null.\n");
		return -EINVAL;
	}

	if (!udata->udrv_data->in_addr ||
	    udata->udrv_data->in_len < sizeof(struct hns3_udma_create_jfc_ucmd)) {
		dev_err(udma_dev->dev, "Invalid jfc in_len %u or addr is null.\n",
			udata->udrv_data->in_len);
		return -EINVAL;
	}

	byte = copy_from_user((void *)ucmd, (void *)udata->udrv_data->in_addr,
			      sizeof(struct hns3_udma_create_jfc_ucmd));
	if (byte) {
		dev_err(udma_dev->dev,
			"failed to copy JFC udata, byte = %lu.\n", byte);
		return -EFAULT;
	}

	ret = check_jfc_cfg(udma_dev, cfg);
@@ -208,8 +217,17 @@ static int alloc_jfc_buf(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc,
{
	struct udma_ucontext *udma_uctx = to_udma_ucontext(udata->uctx);
	struct hns3_udma_create_jfc_resp resp = {};
	unsigned long byte;
	int ret;

	if (!udata->udrv_data->out_addr ||
	    udata->udrv_data->out_len < sizeof(resp)) {
		dev_err(udma_dev->dev,
			"Invalid jfc out: len %u or addr is null.\n",
			udata->udrv_data->out_len);
		return -EINVAL;
	}

	ret = alloc_jfc_cqe_buf(udma_dev, udma_jfc, udata, ucmd->buf_addr);
	if (ret)
		return ret;
@@ -224,17 +242,15 @@ static int alloc_jfc_buf(struct udma_dev *udma_dev, struct udma_jfc *udma_jfc,
		udma_jfc->jfc_caps |= HNS3_UDMA_JFC_CAP_RECORD_DB;
	}

	if (udata) {
	resp.jfc_caps = udma_jfc->jfc_caps;
		ret = copy_to_user((void *)udata->udrv_data->out_addr, &resp,
				   min_t(uint32_t, udata->udrv_data->out_len,
					 (uint32_t)sizeof(resp)));
		if (ret) {
	byte = copy_to_user((void *)udata->udrv_data->out_addr, &resp,
			    sizeof(resp));
	if (byte) {
		dev_err(udma_dev->dev,
				"failed to copy jfc resp, ret = %d.\n", ret);
			"failed to copy jfc resp, byte = %lu.\n", byte);
		ret = -EFAULT;
		goto err_copy;
	}
	}

	refcount_set(&udma_jfc->refcount, 1);
	init_completion(&udma_jfc->free);
@@ -730,12 +746,6 @@ void udma_jfc_event(struct udma_dev *udma_dev, uint32_t cqn, int event_type)
	struct udma_jfc *udma_jfc;
	struct ubcore_event event;

	udma_jfc = (struct udma_jfc *)xa_load(&udma_dev->jfc_table.xa, cqn);
	if (!udma_jfc) {
		dev_warn(dev, "Async event for bogus CQ 0x%06x.\n", cqn);
		return;
	}

	if (event_type != UDMA_EVENT_TYPE_JFC_ACCESS_ERROR &&
	    event_type != UDMA_EVENT_TYPE_JFC_OVERFLOW) {
		dev_err(dev, "Unexpected event type 0x%x on CQ 0x%06x.\n",
@@ -743,7 +753,16 @@ void udma_jfc_event(struct udma_dev *udma_dev, uint32_t cqn, int event_type)
		return;
	}

	xa_lock(&udma_dev->jfc_table.xa);
	udma_jfc = (struct udma_jfc *)xa_load(&udma_dev->jfc_table.xa, cqn);
	if (udma_jfc)
		refcount_inc(&udma_jfc->refcount);
	xa_unlock(&udma_dev->jfc_table.xa);

	if (!udma_jfc) {
		dev_warn(dev, "Async event for bogus CQ 0x%06x.\n", cqn);
		return;
	}

	ubcore_jfc = &udma_jfc->ubcore_jfc;
	if (ubcore_jfc->jfae_handler) {
+5 −7
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ static int udma_hw_create_mpt(struct udma_dev *udma_dev,
			      struct udma_cmd_mailbox *mailbox,
			      uint64_t mpt_index)
{
	struct udma_cmq_desc desc;
	struct udma_cmq_desc desc = {};
	struct udma_mbox *mb;

	mb = (struct udma_mbox *)desc.data;
@@ -50,7 +50,7 @@ static int udma_hw_destroy_mpt(struct udma_dev *udma_dev,
			struct udma_cmd_mailbox *mailbox,
			uint64_t mpt_index)
{
	struct udma_cmq_desc desc;
	struct udma_cmq_desc desc = {};
	struct udma_mbox *mb;

	mb = (struct udma_mbox *)desc.data;
@@ -227,8 +227,7 @@ static int udma_seg_enable(struct udma_dev *udma_dev, struct udma_seg *seg)
		goto err_page;
	}

	ret = udma_hw_create_mpt(udma_dev, mailbox,
				 seg_idx & (udma_dev->caps.num_mtpts - 1));
	ret = udma_hw_create_mpt(udma_dev, mailbox, seg_idx);
	if (ret) {
		dev_err(dev, "failed to create mpt, ret = %d.\n", ret);
		goto err_page;
@@ -396,12 +395,11 @@ struct ubcore_target_seg *udma_register_seg(struct ubcore_device *dev,

static void udma_seg_free(struct udma_dev *udma_dev, struct udma_seg *seg)
{
	uint64_t seg_idx = key_to_hw_index(seg->key);
	int ret;

	if (seg->enabled) {
		ret = udma_hw_destroy_mpt(udma_dev, NULL,
					  key_to_hw_index(seg->key) &
					  (udma_dev->caps.num_mtpts - 1));
		ret = udma_hw_destroy_mpt(udma_dev, NULL, seg_idx);
		if (ret)
			dev_err(udma_dev->dev, "failed to destroy mpt, ret = %d.\n",
				ret);
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include <linux/slab.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include "urma/ubcore_opcode.h"
#include "urma/ubcore_types.h"
#include "hns3_udma_device.h"
#include "hns3_udma_common.h"

Loading