uverbs_cmd.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,020 行 · 第 1/4 页

C
2,020
字号
ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file,				const char __user *buf, int in_len,				int out_len){	struct ib_uverbs_post_srq_recv      cmd;	struct ib_uverbs_post_srq_recv_resp resp;	struct ib_recv_wr                  *wr, *next, *bad_wr;	struct ib_srq                      *srq;	ssize_t                             ret = -EINVAL;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	wr = ib_uverbs_unmarshall_recv(buf + sizeof cmd,				       in_len - sizeof cmd, cmd.wr_count,				       cmd.sge_count, cmd.wqe_size);	if (IS_ERR(wr))		return PTR_ERR(wr);	mutex_lock(&ib_uverbs_idr_mutex);	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);	if (!srq || srq->uobject->context != file->ucontext)		goto out;	resp.bad_wr = 0;	ret = srq->device->post_srq_recv(srq, wr, &bad_wr);	if (ret)		for (next = wr; next; next = next->next) {			++resp.bad_wr;			if (next == bad_wr)				break;		}	if (copy_to_user((void __user *) (unsigned long) cmd.response,			 &resp, sizeof resp))		ret = -EFAULT;out:	mutex_unlock(&ib_uverbs_idr_mutex);	while (wr) {		next = wr->next;		kfree(wr);		wr = next;	}	return ret ? ret : in_len;}ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file,			    const char __user *buf, int in_len,			    int out_len){	struct ib_uverbs_create_ah	 cmd;	struct ib_uverbs_create_ah_resp	 resp;	struct ib_uobject		*uobj;	struct ib_pd			*pd;	struct ib_ah			*ah;	struct ib_ah_attr		attr;	int ret;	if (out_len < sizeof resp)		return -ENOSPC;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);	if (!uobj)		return -ENOMEM;	mutex_lock(&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;	}	uobj->user_handle = cmd.user_handle;	uobj->context     = file->ucontext;	attr.dlid 	       = cmd.attr.dlid;	attr.sl 	       = cmd.attr.sl;	attr.src_path_bits     = cmd.attr.src_path_bits;	attr.static_rate       = cmd.attr.static_rate;	attr.ah_flags          = cmd.attr.is_global ? IB_AH_GRH : 0;	attr.port_num 	       = cmd.attr.port_num;	attr.grh.flow_label    = cmd.attr.grh.flow_label;	attr.grh.sgid_index    = cmd.attr.grh.sgid_index;	attr.grh.hop_limit     = cmd.attr.grh.hop_limit;	attr.grh.traffic_class = cmd.attr.grh.traffic_class;	memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16);	ah = ib_create_ah(pd, &attr);	if (IS_ERR(ah)) {		ret = PTR_ERR(ah);		goto err_up;	}	ah->uobject = uobj;retry:	if (!idr_pre_get(&ib_uverbs_ah_idr, GFP_KERNEL)) {		ret = -ENOMEM;		goto err_destroy;	}	ret = idr_get_new(&ib_uverbs_ah_idr, ah, &uobj->id);	if (ret == -EAGAIN)		goto retry;	if (ret)		goto err_destroy;	resp.ah_handle = uobj->id;	if (copy_to_user((void __user *) (unsigned long) cmd.response,			 &resp, sizeof resp)) {		ret = -EFAULT;		goto err_idr;	}	mutex_lock(&file->mutex);	list_add_tail(&uobj->list, &file->ucontext->ah_list);	mutex_unlock(&file->mutex);	mutex_unlock(&ib_uverbs_idr_mutex);	return in_len;err_idr:	idr_remove(&ib_uverbs_ah_idr, uobj->id);err_destroy:	ib_destroy_ah(ah);err_up:	mutex_unlock(&ib_uverbs_idr_mutex);	kfree(uobj);	return ret;}ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file,			     const char __user *buf, int in_len, int out_len){	struct ib_uverbs_destroy_ah cmd;	struct ib_ah		   *ah;	struct ib_uobject	   *uobj;	int			    ret = -EINVAL;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	mutex_lock(&ib_uverbs_idr_mutex);	ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle);	if (!ah || ah->uobject->context != file->ucontext)		goto out;	uobj = ah->uobject;	ret = ib_destroy_ah(ah);	if (ret)		goto out;	idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle);	mutex_lock(&file->mutex);	list_del(&uobj->list);	mutex_unlock(&file->mutex);	kfree(uobj);out:	mutex_unlock(&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;	struct ib_uqp_object         *uobj;	struct ib_uverbs_mcast_entry *mcast;	int                           ret = -EINVAL;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	mutex_lock(&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_uqp_object, uevent.uobject);	list_for_each_entry(mcast, &uobj->mcast_list, list)		if (cmd.mlid == mcast->lid &&		    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {			ret = 0;			goto out;		}	mcast = kmalloc(sizeof *mcast, GFP_KERNEL);	if (!mcast) {		ret = -ENOMEM;		goto out;	}	mcast->lid = cmd.mlid;	memcpy(mcast->gid.raw, cmd.gid, sizeof mcast->gid.raw);	ret = ib_attach_mcast(qp, &mcast->gid, cmd.mlid);	if (!ret) {		uobj = container_of(qp->uobject, struct ib_uqp_object,				    uevent.uobject);		list_add_tail(&mcast->list, &uobj->mcast_list);	} else		kfree(mcast);out:	mutex_unlock(&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_uqp_object         *uobj;	struct ib_qp                 *qp;	struct ib_uverbs_mcast_entry *mcast;	int                           ret = -EINVAL;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	mutex_lock(&ib_uverbs_idr_mutex);	qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle);	if (!qp || qp->uobject->context != file->ucontext)		goto out;	ret = ib_detach_mcast(qp, (union ib_gid *) cmd.gid, cmd.mlid);	if (ret)		goto out;	uobj = container_of(qp->uobject, struct ib_uqp_object, uevent.uobject);	list_for_each_entry(mcast, &uobj->mcast_list, list)		if (cmd.mlid == mcast->lid &&		    !memcmp(cmd.gid, mcast->gid.raw, sizeof mcast->gid.raw)) {			list_del(&mcast->list);			kfree(mcast);			break;		}out:	mutex_unlock(&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;	mutex_lock(&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;	resp.max_wr     = attr.attr.max_wr;	resp.max_sge    = attr.attr.max_sge;	if (copy_to_user((void __user *) (unsigned long) cmd.response,			 &resp, sizeof resp)) {		ret = -EFAULT;		goto err_idr;	}	mutex_lock(&file->mutex);	list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list);	mutex_unlock(&file->mutex);	mutex_unlock(&ib_uverbs_idr_mutex);	return in_len;err_idr:	idr_remove(&ib_uverbs_srq_idr, uobj->uobject.id);err_destroy:	ib_destroy_srq(srq);	atomic_dec(&pd->usecnt);err_up:	mutex_unlock(&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;	mutex_lock(&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.srq_limit = cmd.srq_limit;	ret = ib_modify_srq(srq, &attr, cmd.attr_mask);out:	mutex_unlock(&ib_uverbs_idr_mutex);	return ret ? ret : in_len;}ssize_t ib_uverbs_query_srq(struct ib_uverbs_file *file,			    const char __user *buf,			    int in_len, int out_len){	struct ib_uverbs_query_srq      cmd;	struct ib_uverbs_query_srq_resp resp;	struct ib_srq_attr              attr;	struct ib_srq                   *srq;	int                             ret;	if (out_len < sizeof resp)		return -ENOSPC;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	mutex_lock(&ib_uverbs_idr_mutex);	srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);	if (srq && srq->uobject->context == file->ucontext)		ret = ib_query_srq(srq, &attr);	else		ret = -EINVAL;	mutex_unlock(&ib_uverbs_idr_mutex);	if (ret)		goto out;	memset(&resp, 0, sizeof resp);	resp.max_wr    = attr.max_wr;	resp.max_sge   = attr.max_sge;	resp.srq_limit = attr.srq_limit;	if (copy_to_user((void __user *) (unsigned long) cmd.response,			 &resp, sizeof resp))		ret = -EFAULT;out:	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;	int                         	  ret = -EINVAL;	if (copy_from_user(&cmd, buf, sizeof cmd))		return -EFAULT;	mutex_lock(&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);	mutex_lock(&file->mutex);	list_del(&uobj->uobject.list);	mutex_unlock(&file->mutex);	ib_uverbs_release_uevent(file, uobj);	resp.events_reported = uobj->events_reported;	kfree(uobj);	if (copy_to_user((void __user *) (unsigned long) cmd.response,			 &resp, sizeof resp))		ret = -EFAULT;out:	mutex_unlock(&ib_uverbs_idr_mutex);	return ret ? ret : in_len;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?