uverbs_cmd.c
来自「底层驱动开发」· C语言 代码 · 共 1,266 行 · 第 1/3 页
C
1,266 行
resp.qpn = qp->qp_num;retry: if (!idr_pre_get(&ib_uverbs_qp_idr, GFP_KERNEL)) { ret = -ENOMEM; goto err_destroy; } ret = idr_get_new(&ib_uverbs_qp_idr, qp, &uobj->uobject.id); if (ret == -EAGAIN) goto retry; if (ret) goto err_destroy; resp.qp_handle = uobj->uobject.id; down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->qp_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(&uobj->uobject.list); up(&file->mutex);err_destroy: ib_destroy_qp(qp);err_up: up(&ib_uverbs_idr_mutex); kfree(uobj); return ret;}ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_modify_qp cmd; struct ib_qp *qp; struct ib_qp_attr *attr; int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; attr = kmalloc(sizeof *attr, GFP_KERNEL); if (!attr) return -ENOMEM; down(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) { ret = -EINVAL; goto out; } attr->qp_state = cmd.qp_state; attr->cur_qp_state = cmd.cur_qp_state; attr->path_mtu = cmd.path_mtu; attr->path_mig_state = cmd.path_mig_state; attr->qkey = cmd.qkey; attr->rq_psn = cmd.rq_psn; attr->sq_psn = cmd.sq_psn; attr->dest_qp_num = cmd.dest_qp_num; attr->qp_access_flags = cmd.qp_access_flags; attr->pkey_index = cmd.pkey_index; attr->alt_pkey_index = cmd.pkey_index; attr->en_sqd_async_notify = cmd.en_sqd_async_notify; attr->max_rd_atomic = cmd.max_rd_atomic; attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic; attr->min_rnr_timer = cmd.min_rnr_timer; attr->port_num = cmd.port_num; attr->timeout = cmd.timeout; attr->retry_cnt = cmd.retry_cnt; attr->rnr_retry = cmd.rnr_retry; attr->alt_port_num = cmd.alt_port_num; attr->alt_timeout = cmd.alt_timeout; memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16); attr->ah_attr.grh.flow_label = cmd.dest.flow_label; attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index; attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit; attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class; attr->ah_attr.dlid = cmd.dest.dlid; attr->ah_attr.sl = cmd.dest.sl; attr->ah_attr.src_path_bits = cmd.dest.src_path_bits; attr->ah_attr.static_rate = cmd.dest.static_rate; attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0; attr->ah_attr.port_num = cmd.dest.port_num; memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16); attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label; attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index; attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit; attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class; attr->alt_ah_attr.dlid = cmd.alt_dest.dlid; attr->alt_ah_attr.sl = cmd.alt_dest.sl; attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits; attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate; attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0; attr->alt_ah_attr.port_num = cmd.alt_dest.port_num; ret = ib_modify_qp(qp, attr, cmd.attr_mask); if (ret) goto out; ret = in_len;out: up(&ib_uverbs_idr_mutex); kfree(attr); return ret;}ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_destroy_qp cmd; struct ib_uverbs_destroy_qp_resp resp; struct ib_qp *qp; struct ib_uevent_object *uobj; struct ib_uverbs_event *evt, *tmp; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; memset(&resp, 0, sizeof resp); down(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (!qp || qp->uobject->context != file->ucontext) goto out; uobj = container_of(qp->uobject, struct ib_uevent_object, uobject); ret = ib_destroy_qp(qp); if (ret) goto out; idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); down(&file->mutex); list_del(&uobj->uobject.list); up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { list_del(&evt->list); kfree(evt); } spin_unlock_irq(&file->async_file.lock); resp.events_reported = uobj->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_attach_mcast(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_attach_mcast cmd; struct ib_qp *qp; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; down(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (qp && qp->uobject->context == file->ucontext) ret = ib_attach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_detach_mcast cmd; struct ib_qp *qp; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; down(&ib_uverbs_idr_mutex); qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); if (qp && qp->uobject->context == file->ucontext) ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid); up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_create_srq cmd; struct ib_uverbs_create_srq_resp resp; struct ib_udata udata; struct ib_uevent_object *uobj; struct ib_pd *pd; struct ib_srq *srq; struct ib_srq_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); if (!pd || pd->uobject->context != file->ucontext) { ret = -EINVAL; goto err_up; } attr.event_handler = ib_uverbs_srq_event_handler; attr.srq_context = file; attr.attr.max_wr = cmd.max_wr; attr.attr.max_sge = cmd.max_sge; attr.attr.srq_limit = cmd.srq_limit; uobj->uobject.user_handle = cmd.user_handle; uobj->uobject.context = file->ucontext; uobj->events_reported = 0; INIT_LIST_HEAD(&uobj->event_list); srq = pd->device->create_srq(pd, &attr, &udata); if (IS_ERR(srq)) { ret = PTR_ERR(srq); goto err_up; } srq->device = pd->device; srq->pd = pd; srq->uobject = &uobj->uobject; srq->event_handler = attr.event_handler; srq->srq_context = attr.srq_context; atomic_inc(&pd->usecnt); atomic_set(&srq->usecnt, 0); memset(&resp, 0, sizeof resp);retry: if (!idr_pre_get(&ib_uverbs_srq_idr, GFP_KERNEL)) { ret = -ENOMEM; goto err_destroy; } ret = idr_get_new(&ib_uverbs_srq_idr, srq, &uobj->uobject.id); if (ret == -EAGAIN) goto retry; if (ret) goto err_destroy; resp.srq_handle = uobj->uobject.id; down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->srq_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(&uobj->uobject.list); up(&file->mutex);err_destroy: ib_destroy_srq(srq);err_up: up(&ib_uverbs_idr_mutex); kfree(uobj); return ret;}ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_modify_srq cmd; struct ib_srq *srq; struct ib_srq_attr attr; int ret; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; down(&ib_uverbs_idr_mutex); srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); if (!srq || srq->uobject->context != file->ucontext) { ret = -EINVAL; goto out; } attr.max_wr = cmd.max_wr; attr.max_sge = cmd.max_sge; attr.srq_limit = cmd.srq_limit; ret = ib_modify_srq(srq, &attr, cmd.attr_mask);out: up(&ib_uverbs_idr_mutex); return ret ? ret : in_len;}ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, const char __user *buf, int in_len, int out_len){ struct ib_uverbs_destroy_srq cmd; struct ib_uverbs_destroy_srq_resp resp; struct ib_srq *srq; struct ib_uevent_object *uobj; struct ib_uverbs_event *evt, *tmp; int ret = -EINVAL; if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; down(&ib_uverbs_idr_mutex); memset(&resp, 0, sizeof resp); srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); if (!srq || srq->uobject->context != file->ucontext) goto out; uobj = container_of(srq->uobject, struct ib_uevent_object, uobject); ret = ib_destroy_srq(srq); if (ret) goto out; idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); down(&file->mutex); list_del(&uobj->uobject.list); up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { list_del(&evt->list); kfree(evt); } spin_unlock_irq(&file->async_file.lock); resp.events_reported = uobj->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;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?