[openib-general] [PATCH][RFC] uverbs SRQ implementation

Roland Dreier rolandd at cisco.com
Wed Aug 3 09:28:04 PDT 2005


Here is a completely untested implementation of the kernel side of
userspace SRQ support.  (Hey, it compiles!)  I should have the
userspace libibverbs and libmthca support soon, and once I've tested
this, I'll commit it.

Feedback in the meantime appreciated, though...

 - R.

--- infiniband/core/uverbs_cmd.c	(revision 2963)
+++ infiniband/core/uverbs_cmd.c	(working copy)
@@ -724,6 +724,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	struct ib_uobject              *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;
@@ -748,9 +749,15 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle);
 	rcq = idr_find(&ib_uverbs_cq_idr, cmd.recv_cq_handle);
 
+	if (cmd.is_srq)
+		srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle);
+	else
+		srq = NULL;
+
 	if (!pd  || pd->uobject->context  != file->ucontext ||
 	    !scq || scq->uobject->context != file->ucontext ||
-	    !rcq || rcq->uobject->context != file->ucontext) {
+	    !rcq || rcq->uobject->context != file->ucontext ||
+	    (cmd.is_srq && (!srq || srq->uobject->context != file->ucontext))) {
 		ret = -EINVAL;
 		goto err_up;
 	}
@@ -759,7 +766,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uv
 	attr.qp_context    = file;
 	attr.send_cq       = scq;
 	attr.recv_cq       = rcq;
-	attr.srq           = NULL;
+	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;
 
@@ -1004,3 +1011,175 @@ ssize_t ib_uverbs_detach_mcast(struct ib
 
 	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_uobject               *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;
+
+	uobj->user_handle = cmd.user_handle;
+	uobj->context     = file->ucontext;
+
+	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;
+	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->id);
+
+	if (ret == -EAGAIN)
+		goto retry;
+	if (ret)
+		goto err_destroy;
+
+	resp.srq_handle = uobj->id;
+
+	spin_lock_irq(&file->ucontext->lock);
+	list_add_tail(&uobj->list, &file->ucontext->srq_list);
+	spin_unlock_irq(&file->ucontext->lock);
+
+	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:
+	spin_lock_irq(&file->ucontext->lock);
+	list_del(&uobj->list);
+	spin_unlock_irq(&file->ucontext->lock);
+
+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_srq               *srq;
+	struct ib_uobject           *uobj;
+	int                          ret = -EINVAL;
+
+	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)
+		goto out;
+
+	uobj = srq->uobject;
+
+	ret = ib_destroy_srq(srq);
+	if (ret)
+		goto out;
+
+	idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle);
+
+	spin_lock_irq(&file->ucontext->lock);
+	list_del(&uobj->list);
+	spin_unlock_irq(&file->ucontext->lock);
+
+	kfree(uobj);
+
+out:
+	up(&ib_uverbs_idr_mutex);
+
+	return ret ? ret : in_len;
+}
--- infiniband/core/uverbs.h	(revision 2963)
+++ infiniband/core/uverbs.h	(working copy)
@@ -99,10 +99,12 @@ extern struct idr ib_uverbs_mw_idr;
 extern struct idr ib_uverbs_ah_idr;
 extern struct idr ib_uverbs_cq_idr;
 extern struct idr ib_uverbs_qp_idr;
+extern struct idr ib_uverbs_srq_idr;
 
 void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
 void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
 void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
 
 int ib_umem_get(struct ib_device *dev, struct ib_umem *mem,
 		void *addr, size_t size, int write);
@@ -131,5 +133,8 @@ IB_UVERBS_DECLARE_CMD(modify_qp);
 IB_UVERBS_DECLARE_CMD(destroy_qp);
 IB_UVERBS_DECLARE_CMD(attach_mcast);
 IB_UVERBS_DECLARE_CMD(detach_mcast);
+IB_UVERBS_DECLARE_CMD(create_srq);
+IB_UVERBS_DECLARE_CMD(modify_srq);
+IB_UVERBS_DECLARE_CMD(destroy_srq);
 
 #endif /* UVERBS_H */
--- infiniband/core/uverbs_main.c	(revision 2963)
+++ infiniband/core/uverbs_main.c	(working copy)
@@ -69,6 +69,7 @@ DEFINE_IDR(ib_uverbs_mw_idr);
 DEFINE_IDR(ib_uverbs_ah_idr);
 DEFINE_IDR(ib_uverbs_cq_idr);
 DEFINE_IDR(ib_uverbs_qp_idr);
+DEFINE_IDR(ib_uverbs_srq_idr);
 
 static spinlock_t map_lock;
 static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -93,6 +94,9 @@ static ssize_t (*uverbs_cmd_table[])(str
 	[IB_USER_VERBS_CMD_DESTROY_QP]    = ib_uverbs_destroy_qp,
 	[IB_USER_VERBS_CMD_ATTACH_MCAST]  = ib_uverbs_attach_mcast,
 	[IB_USER_VERBS_CMD_DETACH_MCAST]  = ib_uverbs_detach_mcast,
+	[IB_USER_VERBS_CMD_CREATE_SRQ]    = ib_uverbs_create_qp,
+	[IB_USER_VERBS_CMD_MODIFY_SRQ]    = ib_uverbs_modify_qp,
+	[IB_USER_VERBS_CMD_DESTROY_SRQ]   = ib_uverbs_destroy_qp,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -127,7 +131,14 @@ static int ib_dealloc_ucontext(struct ib
 		kfree(uobj);
 	}
 
-	/* XXX Free SRQs */
+	list_for_each_entry_safe(uobj, tmp, &context->srq_list, list) {
+		struct ib_srq *srq = idr_find(&ib_uverbs_srq_idr, uobj->id);
+		idr_remove(&ib_uverbs_srq_idr, uobj->id);
+		ib_destroy_srq(srq);
+		list_del(&uobj->list);
+		kfree(uobj);
+	}
+
 	/* XXX Free MWs */
 
 	list_for_each_entry_safe(uobj, tmp, &context->mr_list, list) {
@@ -345,6 +356,13 @@ void ib_uverbs_qp_event_handler(struct i
 				event->event);
 }
 
+void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
+{
+	ib_uverbs_async_handler(context_ptr,
+				event->element.srq->uobject->user_handle,
+				event->event);
+}
+
 static void ib_uverbs_event_handler(struct ib_event_handler *handler,
 				    struct ib_event *event)
 {
--- infiniband/include/ib_user_verbs.h	(revision 2963)
+++ infiniband/include/ib_user_verbs.h	(working copy)
@@ -78,7 +78,12 @@ enum {
 	IB_USER_VERBS_CMD_POST_SEND,
 	IB_USER_VERBS_CMD_POST_RECV,
 	IB_USER_VERBS_CMD_ATTACH_MCAST,
-	IB_USER_VERBS_CMD_DETACH_MCAST
+	IB_USER_VERBS_CMD_DETACH_MCAST,
+	IB_USER_VERBS_CMD_CREATE_SRQ,
+	IB_USER_VERBS_CMD_MODIFY_SRQ,
+	IB_USER_VERBS_CMD_QUERY_SRQ,
+	IB_USER_VERBS_CMD_DESTROY_SRQ,
+	IB_USER_VERBS_CMD_POST_SRQ_RECV
 };
 
 /*
@@ -386,4 +391,32 @@ struct ib_uverbs_detach_mcast {
 	__u64 driver_data[0];
 };
 
+struct ib_uverbs_create_srq {
+	__u64 response;
+	__u64 user_handle;
+	__u32 pd_handle;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_create_srq_resp {
+	__u32 srq_handle;
+};
+
+struct ib_uverbs_modify_srq {
+	__u32 srq_handle;
+	__u32 attr_mask;
+	__u32 max_wr;
+	__u32 max_sge;
+	__u32 srq_limit;
+	__u32 reserved;
+	__u64 driver_data[0];
+};
+
+struct ib_uverbs_destroy_srq {
+	__u32 srq_handle;
+};
+
 #endif /* IB_USER_VERBS_H */



More information about the general mailing list