Unverified Commit 9c56bd59 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!6063 RDMA/hns: Some bugfixes and cleanups

Merge Pull Request from: @stinft 
 
Some bugfixes and cleanups
Chengchang Tang (6):
   RDMA/hns: fix iommu_map_sg() failed when MR bigger than 4G
   RDMA/hns: Use complete parentheses in macros
   RDMA/hns: Remove extra blank line in get_sge_num_from_max_inl_data()
   RDMA/hns: Fix missing resetting notify
   RDMA/hns: Fix missing capacities in query_device()
   RDMA/hns: Fix cpu stuck by printings during reset
 wenglianfa (3):
   RDMA/hns: Fix simultaneous reset and resource deregistration
   RDMA/hns: Fix the overflow risk of hem_list_calc_ba_range()
   RDMA/hns: Fix long waiting cmd event when reset
https://gitee.com/openeuler/kernel/issues/I9FIHP 
 
Link:https://gitee.com/openeuler/kernel/pulls/6063

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Reviewed-by: default avatarChengchang Tang <tangchengchang@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 96c1e1c4 31eccbf1
Loading
Loading
Loading
Loading
+85 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
 * Copyright 2019 Marvell. All rights reserved.
 */
#include <linux/xarray.h>
#include <linux/sched/mm.h>
#include "uverbs.h"
#include "core_priv.h"

@@ -365,3 +366,87 @@ int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
						 U32_MAX);
}
EXPORT_SYMBOL(rdma_user_mmap_entry_insert);

void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
{
	struct rdma_umap_priv *priv, *next_priv;

	lockdep_assert_held(&ufile->hw_destroy_rwsem);

	while (1) {
		struct mm_struct *mm = NULL;

		/* Get an arbitrary mm pointer that hasn't been cleaned yet */
		mutex_lock(&ufile->umap_lock);
		while (!list_empty(&ufile->umaps)) {
			int ret;

			priv = list_first_entry(&ufile->umaps,
						struct rdma_umap_priv, list);
			mm = priv->vma->vm_mm;
			ret = mmget_not_zero(mm);
			if (!ret) {
				list_del_init(&priv->list);
				if (priv->entry) {
					rdma_user_mmap_entry_put(priv->entry);
					priv->entry = NULL;
				}
				mm = NULL;
				continue;
			}
			break;
		}
		mutex_unlock(&ufile->umap_lock);
		if (!mm)
			return;

		/*
		 * The umap_lock is nested under mmap_lock since it used within
		 * the vma_ops callbacks, so we have to clean the list one mm
		 * at a time to get the lock ordering right. Typically there
		 * will only be one mm, so no big deal.
		 */
		mmap_read_lock(mm);
		mutex_lock(&ufile->umap_lock);
		list_for_each_entry_safe(priv, next_priv, &ufile->umaps, list) {
			struct vm_area_struct *vma = priv->vma;

			if (vma->vm_mm != mm)
				continue;
			list_del_init(&priv->list);

			zap_vma_ptes(vma, vma->vm_start,
				     vma->vm_end - vma->vm_start);

			if (priv->entry) {
				rdma_user_mmap_entry_put(priv->entry);
				priv->entry = NULL;
			}
		}
		mutex_unlock(&ufile->umap_lock);
		mmap_read_unlock(mm);
		mmput(mm);
	}
}
EXPORT_SYMBOL(uverbs_user_mmap_disassociate);

/**
 * rdma_user_mmap_disassociate() - disassociate the mmap from the ucontext.
 *
 * @ucontext: associated user context.
 *
 * This function should be called by drivers that need to disable mmap for
 * some ucontexts.
 */
void rdma_user_mmap_disassociate(struct ib_ucontext *ucontext)
{
	struct ib_uverbs_file *ufile = ucontext->ufile;

	/* Racing with uverbs_destroy_ufile_hw */
	if (!down_read_trylock(&ufile->hw_destroy_rwsem))
		return;

	uverbs_user_mmap_disassociate(ufile);
	up_read(&ufile->hw_destroy_rwsem);
}
EXPORT_SYMBOL(rdma_user_mmap_disassociate);
+0 −1
Original line number Diff line number Diff line
@@ -149,7 +149,6 @@ void uverbs_disassociate_api(struct uverbs_api *uapi);
void uverbs_destroy_api(struct uverbs_api *uapi);
void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
			      unsigned int num_attrs);
void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile);

extern const struct uapi_definition uverbs_def_obj_async_fd[];
extern const struct uapi_definition uverbs_def_obj_counters[];
+0 −64
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@
#include <linux/cdev.h>
#include <linux/anon_inodes.h>
#include <linux/slab.h>
#include <linux/sched/mm.h>

#include <linux/uaccess.h>

@@ -817,69 +816,6 @@ static const struct vm_operations_struct rdma_umap_ops = {
	.fault = rdma_umap_fault,
};

void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
{
	struct rdma_umap_priv *priv, *next_priv;

	lockdep_assert_held(&ufile->hw_destroy_rwsem);

	while (1) {
		struct mm_struct *mm = NULL;

		/* Get an arbitrary mm pointer that hasn't been cleaned yet */
		mutex_lock(&ufile->umap_lock);
		while (!list_empty(&ufile->umaps)) {
			int ret;

			priv = list_first_entry(&ufile->umaps,
						struct rdma_umap_priv, list);
			mm = priv->vma->vm_mm;
			ret = mmget_not_zero(mm);
			if (!ret) {
				list_del_init(&priv->list);
				if (priv->entry) {
					rdma_user_mmap_entry_put(priv->entry);
					priv->entry = NULL;
				}
				mm = NULL;
				continue;
			}
			break;
		}
		mutex_unlock(&ufile->umap_lock);
		if (!mm)
			return;

		/*
		 * The umap_lock is nested under mmap_lock since it used within
		 * the vma_ops callbacks, so we have to clean the list one mm
		 * at a time to get the lock ordering right. Typically there
		 * will only be one mm, so no big deal.
		 */
		mmap_read_lock(mm);
		mutex_lock(&ufile->umap_lock);
		list_for_each_entry_safe (priv, next_priv, &ufile->umaps,
					  list) {
			struct vm_area_struct *vma = priv->vma;

			if (vma->vm_mm != mm)
				continue;
			list_del_init(&priv->list);

			zap_vma_ptes(vma, vma->vm_start,
				     vma->vm_end - vma->vm_start);

			if (priv->entry) {
				rdma_user_mmap_entry_put(priv->entry);
				priv->entry = NULL;
			}
		}
		mutex_unlock(&ufile->umap_lock);
		mmap_read_unlock(mm);
		mmput(mm);
	}
}

/*
 * ib_uverbs_open() does not need the BKL:
 *
+27 −6
Original line number Diff line number Diff line
@@ -179,8 +179,11 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
	ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_CQC,
				      hr_cq->cqn);
	if (ret)
		dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret,
			hr_cq->cqn);
		dev_err_ratelimited(dev,
				    "DESTROY_CQ failed (%d) for CQN %06lx\n",
				    ret, hr_cq->cqn);
	if (ret == -EBUSY)
		hr_cq->delayed_destroy_flag = true;

	xa_erase(&cq_table->array, hr_cq->cqn);

@@ -192,6 +195,10 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
		complete(&hr_cq->free);
	wait_for_completion(&hr_cq->free);

	/* this resource will be freed when the driver is uninstalled, so
	 * no memory leak will occur.
	 */
	if (!hr_cq->delayed_destroy_flag)
		hns_roce_table_put(hr_dev, &cq_table->table, hr_cq->cqn);
}

@@ -202,6 +209,10 @@ static int alloc_cq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
	struct hns_roce_buf_attr buf_attr = {};
	int ret;

	hr_cq->mtr_node = kvmalloc(sizeof(*hr_cq->mtr_node), GFP_KERNEL);
	if (!hr_cq->mtr_node)
		return -ENOMEM;

	buf_attr.page_shift = hr_dev->caps.cqe_buf_pg_sz + PAGE_SHIFT;
	buf_attr.region[0].size = hr_cq->cq_depth * hr_cq->cqe_size;
	buf_attr.region[0].hopnum = hr_dev->caps.cqe_hop_num;
@@ -210,15 +221,24 @@ static int alloc_cq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
	ret = hns_roce_mtr_create(hr_dev, &hr_cq->mtr, &buf_attr,
				  hr_dev->caps.cqe_ba_pg_sz + PAGE_SHIFT,
				  udata, addr);
	if (ret)
	if (ret) {
		ibdev_err(ibdev, "failed to alloc CQ mtr, ret = %d.\n", ret);
		kvfree(hr_cq->mtr_node);
		hr_cq->mtr_node = NULL;
	}

	return ret;
}

static void free_cq_buf(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq)
{
	if (hr_cq->delayed_destroy_flag) {
		hns_roce_add_unfree_mtr(hr_cq->mtr_node, hr_dev, &hr_cq->mtr);
	} else {
		hns_roce_mtr_destroy(hr_dev, &hr_cq->mtr);
		kvfree(hr_cq->mtr_node);
		hr_cq->mtr_node = NULL;
	}
}

static int alloc_cq_db(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
@@ -269,7 +289,8 @@ static void free_cq_db(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq,
		uctx = rdma_udata_to_drv_context(udata,
						 struct hns_roce_ucontext,
						 ibucontext);
		hns_roce_db_unmap_user(uctx, &hr_cq->db);
		hns_roce_db_unmap_user(uctx, &hr_cq->db,
				       hr_cq->delayed_destroy_flag);
	} else {
		hns_roce_free_db(hr_dev, &hr_cq->db);
	}
+25 −6
Original line number Diff line number Diff line
@@ -24,7 +24,7 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
	page = kmalloc(sizeof(*page), GFP_KERNEL);
	if (!page) {
		ret = -ENOMEM;
		goto out;
		goto err_out;
	}

	refcount_set(&page->refcount, 1);
@@ -33,8 +33,12 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
				 PAGE_SIZE, 0);
	if (IS_ERR(page->umem)) {
		ret = PTR_ERR(page->umem);
		kfree(page);
		goto out;
		goto err_page;
	}
	page->umem_node = kvmalloc(sizeof(*page->umem_node), GFP_KERNEL);
	if (!page->umem_node) {
		ret = -ENOMEM;
		goto err_umem;
	}

	list_add(&page->list, &context->page_list);
@@ -46,21 +50,36 @@ int hns_roce_db_map_user(struct hns_roce_ucontext *context, unsigned long virt,
	db->u.user_page = page;
	refcount_inc(&page->refcount);

out:
	mutex_unlock(&context->page_mutex);
	return 0;

err_umem:
	ib_umem_release(page->umem);
err_page:
	kfree(page);
err_out:
	mutex_unlock(&context->page_mutex);

	return ret;
}

void hns_roce_db_unmap_user(struct hns_roce_ucontext *context,
			    struct hns_roce_db *db)
			    struct hns_roce_db *db,
			    bool delayed_unmap_flag)
{
	struct hns_roce_dev *hr_dev = to_hr_dev(context->ibucontext.device);

	mutex_lock(&context->page_mutex);

	refcount_dec(&db->u.user_page->refcount);
	if (refcount_dec_if_one(&db->u.user_page->refcount)) {
		list_del(&db->u.user_page->list);
		if (delayed_unmap_flag) {
			hns_roce_add_unfree_umem(db->u.user_page, hr_dev);
		} else {
			ib_umem_release(db->u.user_page->umem);
			kvfree(db->u.user_page->umem_node);
		}
		kfree(db->u.user_page);
	}

Loading