uverbs_cmd.c
来自「底层驱动开发」· C语言 代码 · 共 1,266 行 · 第 1/3 页
C
1,266 行
idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); down(&file->mutex); list_del(&uobj->list); up(&file->mutex); kfree(uobj);out: up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_reg_mr cmd; struct ib_uverbs_reg_mr_resp resp; struct ib_udata udata; struct ib_umem_object *obj; struct ib_pd *pd; struct ib_mr *mr; int ret; if (out_len < sizeof resp) return -ENOSPC; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) return -EINVAL; obj = kmalloc(sizeof *obj, GFP_KERNEL); if (!obj) return -ENOMEM; obj->uobject.context = file->ucontext; /* * We ask for writable memory if any access flags other than * "remote read" are set. "Local write" and "remote write" * obviously require write access. "Remote atomic" can do * things like fetch and add, which will modify memory, and * "MW bind" can change permissions by binding a window. */ ret = ib_umem_get(file->device->ib_dev, &obj->umem, (void *) (unsigned long) cmd.start, cmd.length, !!(cmd.access_flags & ~IB_ACCESS_REMOTE_READ)); if (ret) goto err_free; obj->umem.virt_base = cmd.hca_va; down(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); if (!pd || pd->uobject->context != file->ucontext) { ret = -EINVAL; goto err_up; } if (!pd->device->reg_user_mr) { ret = -ENOSYS; goto err_up; } mr = pd->device->reg_user_mr(pd, &obj->umem, cmd.access_flags, &udata); if (IS_ERR(mr)) { ret = PTR_ERR(mr); goto err_up; } mr->device = pd->device; mr->pd = pd; mr->uobject = &obj->uobject; atomic_inc(&pd->usecnt); atomic_set(&mr->usecnt, 0); memset(&resp, 0, sizeof resp); resp.lkey = mr->lkey; resp.rkey = mr->rkey;retry: if (!idr_pre_get(&ib_uverbs_mr_idr, GFP_KERNEL)) { ret = -ENOMEM; goto err_unreg; } ret = idr_get_new(&ib_uverbs_mr_idr, mr, &obj->uobject.id); if (ret == -EAGAIN) goto retry; if (ret) goto err_unreg; resp.mr_handle = obj->uobject.id; down(&file->mutex); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; goto err_list; } up(&ib_uverbs_idr_mutex); return in_len;err_list: down(&file->mutex); list_del(&obj->uobject.list); up(&file->mutex);err_unreg: ib_dereg_mr(mr);err_up: up(&ib_uverbs_idr_mutex); ib_umem_release(file->device->ib_dev, &obj->umem);err_free: kfree(obj); return ret;}ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_dereg_mr cmd; struct ib_mr *mr; struct ib_umem_object *memobj; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; down(&ib_uverbs_idr_mutex); mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); if (!mr || mr->uobject->context != file->ucontext) goto out; memobj = container_of(mr->uobject, struct ib_umem_object, uobject); ret = ib_dereg_mr(mr); if (ret) goto out; idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); down(&file->mutex); list_del(&memobj->uobject.list); up(&file->mutex); ib_umem_release(file->device->ib_dev, &memobj->umem); kfree(memobj);out: up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_create_cq cmd; struct ib_uverbs_create_cq_resp resp; struct ib_udata udata; struct ib_ucq_object *uobj; struct ib_cq *cq; int ret; if (out_len < sizeof resp) return -ENOSPC; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); if (cmd.event_handler >= file->device->num_comp) return -EINVAL; uobj = kmalloc(sizeof *uobj, GFP_KERNEL); if (!uobj) return -ENOMEM; uobj->uobject.user_handle = cmd.user_handle; uobj->uobject.context = file->ucontext; uobj->comp_events_reported = 0; uobj->async_events_reported = 0; INIT_LIST_HEAD(&uobj->comp_list); INIT_LIST_HEAD(&uobj->async_list); cq = file->device->ib_dev->create_cq(file->device->ib_dev, cmd.cqe, file->ucontext, &udata); if (IS_ERR(cq)) { ret = PTR_ERR(cq); goto err; } cq->device = file->device->ib_dev; cq->uobject = &uobj->uobject; cq->comp_handler = ib_uverbs_comp_handler; cq->event_handler = ib_uverbs_cq_event_handler; cq->cq_context = file; atomic_set(&cq->usecnt, 0);retry: if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { ret = -ENOMEM; goto err_cq; } down(&ib_uverbs_idr_mutex); ret = idr_get_new(&ib_uverbs_cq_idr, cq, &uobj->uobject.id); up(&ib_uverbs_idr_mutex); if (ret == -EAGAIN) goto retry; if (ret) goto err_cq; down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); up(&file->mutex); memset(&resp, 0, sizeof resp); resp.cq_handle = uobj->uobject.id; resp.cqe = cq->cqe; if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { ret = -EFAULT; goto err_list; } return in_len;err_list: down(&file->mutex); list_del(&uobj->uobject.list); up(&file->mutex); down(&ib_uverbs_idr_mutex); idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); up(&ib_uverbs_idr_mutex);err_cq: ib_destroy_cq(cq);err: kfree(uobj); return ret;}ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_destroy_cq cmd; struct ib_uverbs_destroy_cq_resp resp; struct ib_cq *cq; struct ib_ucq_object *uobj; struct ib_uverbs_event *evt, *tmp; u64 user_handle; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; memset(&resp, 0, sizeof resp); down(&ib_uverbs_idr_mutex); cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); if (!cq || cq->uobject->context != file->ucontext) goto out; user_handle = cq->uobject->user_handle; uobj = container_of(cq->uobject, struct ib_ucq_object, uobject); ret = ib_destroy_cq(cq); if (ret) goto out; idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); down(&file->mutex); list_del(&uobj->uobject.list); up(&file->mutex); spin_lock_irq(&file->comp_file[0].lock); list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) { list_del(&evt->list); kfree(evt); } spin_unlock_irq(&file->comp_file[0].lock); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->async_list, obj_list) { list_del(&evt->list); kfree(evt); } spin_unlock_irq(&file->async_file.lock); resp.comp_events_reported = uobj->comp_events_reported; resp.async_events_reported = uobj->async_events_reported; kfree(uobj); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) ret = -EFAULT;out: up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_create_qp cmd; struct ib_uverbs_create_qp_resp resp; struct ib_udata udata; struct ib_uevent_object *uobj; struct ib_pd *pd; struct ib_cq *scq, *rcq; struct ib_srq *srq; struct ib_qp *qp; struct ib_qp_init_attr attr; int ret; if (out_len < sizeof resp) return -ENOSPC; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); uobj = kmalloc(sizeof *uobj, GFP_KERNEL); if (!uobj) return -ENOMEM; down(&ib_uverbs_idr_mutex); pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle); srq = cmd.is_srq ? idr_find(&ib_uverbs_srq_idr, cmd.srq_handle) : NULL; if (!pd || pd->uobject->context != file->ucontext || !scq || scq->uobject->context != file->ucontext || !rcq || rcq->uobject->context != file->ucontext || (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) { ret = -EINVAL; goto err_up; } attr.event_handler = ib_uverbs_qp_event_handler; attr.qp_context = file; attr.send_cq = scq; attr.recv_cq = rcq; attr.srq = srq; attr.sq_sig_type = cmd.sq_sig_all ? IB_SIGNAL_ALL_WR : IB_SIGNAL_REQ_WR; attr.qp_type = cmd.qp_type; attr.cap.max_send_wr = cmd.max_send_wr; attr.cap.max_recv_wr = cmd.max_recv_wr; attr.cap.max_send_sge = cmd.max_send_sge; attr.cap.max_recv_sge = cmd.max_recv_sge; attr.cap.max_inline_data = cmd.max_inline_data; uobj->uobject.user_handle = cmd.user_handle; uobj->uobject.context = file->ucontext; uobj->events_reported = 0; INIT_LIST_HEAD(&uobj->event_list); qp = pd->device->create_qp(pd, &attr, &udata); if (IS_ERR(qp)) { ret = PTR_ERR(qp); goto err_up; } qp->device = pd->device; qp->pd = pd; qp->send_cq = attr.send_cq; qp->recv_cq = attr.recv_cq; qp->srq = attr.srq; qp->uobject = &uobj->uobject; qp->event_handler = attr.event_handler; qp->qp_context = attr.qp_context; qp->qp_type = attr.qp_type; atomic_inc(&pd->usecnt); atomic_inc(&attr.send_cq->usecnt); atomic_inc(&attr.recv_cq->usecnt); if (attr.srq) atomic_inc(&attr.srq->usecnt); memset(&resp, 0, sizeof resp);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?