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 + -
显示快捷键?