diff --git a/drivers/infiniband/core/ib_core_uverbs.c b/drivers/infiniband/core/ib_core_uverbs.c index 4e27389a75adf4243730221322e1830cfe8e8d85..e6405c679cee56531ffc6e7af1ab7e2e631cbc69 100644 --- a/drivers/infiniband/core/ib_core_uverbs.c +++ b/drivers/infiniband/core/ib_core_uverbs.c @@ -367,11 +367,12 @@ int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext, } EXPORT_SYMBOL(rdma_user_mmap_entry_insert); +#if IS_ENABLED(CONFIG_MMU) void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) { struct rdma_umap_priv *priv, *next_priv; - lockdep_assert_held(&ufile->hw_destroy_rwsem); + mutex_lock(&ufile->disassociation_lock); while (1) { struct mm_struct *mm = NULL; @@ -397,8 +398,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) break; } mutex_unlock(&ufile->umap_lock); - if (!mm) + if (!mm) { + mutex_unlock(&ufile->disassociation_lock); return; + } /* * The umap_lock is nested under mmap_lock since it used within @@ -427,26 +430,22 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) mmap_read_unlock(mm); mmput(mm); } + + mutex_unlock(&ufile->disassociation_lock); } EXPORT_SYMBOL(uverbs_user_mmap_disassociate); /** - * rdma_user_mmap_disassociate() - disassociate the mmap from the ucontext. - * - * @ucontext: associated user context. + * rdma_user_mmap_disassociate() - Revoke mmaps for a device + * @device: device to revoke * - * This function should be called by drivers that need to disable mmap for - * some ucontexts. + * This function should be called by drivers that need to disable mmaps for the + * device, for instance because it is going to be reset. */ 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); + if (ucontext->ufile) + uverbs_user_mmap_disassociate(ucontext->ufile); } EXPORT_SYMBOL(rdma_user_mmap_disassociate); +#endif diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h index ad01fbd52c48492667bb042d8c00bbc73d218fc1..f0c668addcbf38dde21738abcd4d59ef5cf5fbf3 100644 --- a/drivers/infiniband/core/rdma_core.h +++ b/drivers/infiniband/core/rdma_core.h @@ -163,6 +163,8 @@ extern const struct uapi_definition uverbs_def_obj_srq[]; extern const struct uapi_definition uverbs_def_obj_wq[]; extern const struct uapi_definition uverbs_def_write_intf[]; +extern struct ib_client uverbs_client; + static inline const struct uverbs_api_write_method * uapi_get_method(const struct uverbs_api *uapi, u32 command) { diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 821d93c8f7123ce1da41d91e88fba9f044dc8e79..dfd2e5a86e6fe5f3b6e027b90924d7802d729eaf 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -160,6 +160,8 @@ struct ib_uverbs_file { struct page *disassociate_page; struct xarray idr; + + struct mutex disassociation_lock; }; struct ib_uverbs_event { diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index f1db48c2ce974ce474be91f93c427a06f638fc9a..36fced49737697d765f9497235cb682662c1de32 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -216,6 +216,7 @@ void ib_uverbs_release_file(struct kref *ref) if (file->disassociate_page) __free_pages(file->disassociate_page, 0); + mutex_destroy(&file->disassociation_lock); mutex_destroy(&file->umap_lock); mutex_destroy(&file->ucontext_lock); kfree(file); @@ -699,8 +700,13 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) ret = PTR_ERR(ucontext); goto out; } + + mutex_lock(&file->disassociation_lock); + vma->vm_ops = &rdma_umap_ops; ret = ucontext->device->ops.mmap(ucontext, vma); + + mutex_unlock(&file->disassociation_lock); out: srcu_read_unlock(&file->device->disassociate_srcu, srcu_key); return ret; @@ -722,6 +728,8 @@ static void rdma_umap_open(struct vm_area_struct *vma) /* We are racing with disassociation */ if (!down_read_trylock(&ufile->hw_destroy_rwsem)) goto out_zap; + mutex_lock(&ufile->disassociation_lock); + /* * Disassociation already completed, the VMA should already be zapped. */ @@ -733,10 +741,12 @@ static void rdma_umap_open(struct vm_area_struct *vma) goto out_unlock; rdma_umap_priv_init(priv, vma, opriv->entry); + mutex_unlock(&ufile->disassociation_lock); up_read(&ufile->hw_destroy_rwsem); return; out_unlock: + mutex_unlock(&ufile->disassociation_lock); up_read(&ufile->hw_destroy_rwsem); out_zap: /* @@ -970,7 +980,7 @@ static int ib_uverbs_get_nl_info(struct ib_device *ibdev, void *client_data, return 0; } -static struct ib_client uverbs_client = { +struct ib_client uverbs_client = { .name = "uverbs", .no_kverbs_req = true, .add = ib_uverbs_add_one, diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index bc0b944ecfacc8d615a8bdf615b6c069caba3e54..6eb1fcf24272c1b1591f715fd05a17f54bbc0282 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -7615,13 +7615,14 @@ int hns_roce_bond_uninit_client(struct hns_roce_bond_group *bond_grp, static void hns_roce_v2_reset_notify_user(struct hns_roce_dev *hr_dev) { - struct hns_roce_ucontext *uctx, *tmp; + struct hns_roce_v2_reset_state *state; - mutex_lock(&hr_dev->uctx_list_mutex); - list_for_each_entry_safe(uctx, tmp, &hr_dev->uctx_list, list) { - rdma_user_mmap_disassociate(&uctx->ibucontext); - } - mutex_unlock(&hr_dev->uctx_list_mutex); + state = (struct hns_roce_v2_reset_state *)hr_dev->reset_kaddr; + + state->reset_state = HNS_ROCE_IS_RESETTING; + state->hw_ready = 0; + /* Ensure reset state was flushed in memory */ + wmb(); } static void hns_roce_v2_reset_notify_cmd(struct hns_roce_dev *hr_dev) @@ -7641,6 +7642,7 @@ static void hns_roce_v2_reset_notify_cmd(struct hns_roce_dev *hr_dev) static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) { struct hns_roce_dev *hr_dev; + struct hns_roce_ucontext *uctx, *tmp; if (handle->rinfo.instance_state != HNS_ROCE_STATE_INITED) { set_bit(HNS_ROCE_RST_DIRECT_RETURN, &handle->rinfo.state); @@ -7657,6 +7659,12 @@ static int hns_roce_hw_v2_reset_notify_down(struct hnae3_handle *handle) hr_dev->active = false; hr_dev->dis_db = true; + mutex_lock(&hr_dev->uctx_list_mutex); + list_for_each_entry_safe(uctx, tmp, &hr_dev->uctx_list, list) { + rdma_user_mmap_disassociate(&uctx->ibucontext); + } + mutex_unlock(&hr_dev->uctx_list_mutex); + hns_roce_v2_reset_notify_user(hr_dev); hr_dev->state = HNS_ROCE_DEVICE_STATE_RST_DOWN; diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index b637424f0a51ac3ce70497caef7bac667913e7d8..1302c58c3937c4490366b94585fc66dcb5e3cf31 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -683,6 +683,11 @@ static int hns_roce_mmap(struct ib_ucontext *uctx, struct vm_area_struct *vma) pgprot_t prot; int ret; + if (hr_dev->dis_db) { + atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]); + return -EPERM; + } + rdma_entry = rdma_user_mmap_entry_get_pgoff(uctx, vma->vm_pgoff); if (!rdma_entry) { atomic64_inc(&hr_dev->dfx_cnt[HNS_ROCE_DFX_MMAP_ERR_CNT]); diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h index 7e602a7e653312acd24001d3541d457e80cdc86a..9bd7c9f7fa0bd6a743a39853b0d0c92f24cbdaf6 100644 --- a/include/rdma/ib_verbs.h +++ b/include/rdma/ib_verbs.h @@ -2949,7 +2949,19 @@ int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext, struct rdma_user_mmap_entry *entry, size_t length, u32 min_pgoff, u32 max_pgoff); + +#if IS_ENABLED(CONFIG_MMU) +void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile); void rdma_user_mmap_disassociate(struct ib_ucontext *ucontext); +#else +static inline void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) +{ +} + +static inline void rdma_user_mmap_disassociate(struct ib_ucontext *ucontext) +{ +} +#endif static inline int rdma_user_mmap_entry_insert_exact(struct ib_ucontext *ucontext, @@ -4729,7 +4741,6 @@ void rdma_roce_rescan_device(struct ib_device *ibdev); struct ib_ucontext *ib_uverbs_get_ucontext_file(struct ib_uverbs_file *ufile); int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs); -void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile); struct net_device *rdma_alloc_netdev(struct ib_device *device, u32 port_num, enum rdma_netdev_t type, const char *name,