[PATCH] IB: userspace SRQ support

Add SRQ support to userspace verbs module.  This adds several commands
and associated structures, but it's OK to do this without bumping the
ABI version because the commands are added at the end of the list so
they don't change the existing numbering.  There are two cases to
worry about:

1. New kernel, old userspace.  This is OK because old userspace simply
   won't try to use the new SRQ commands.  None of the old commands are
   changed.

2. Old kernel, new userspace.  This works perfectly as long as
   userspace doesn't try to use SRQ commands.  If userspace tries to
   use SRQ commands, it will get EINVAL, which is perfectly
   reasonable: the kernel doesn't support SRQs, so we couldn't do any
   better.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index fd8e963..09caf5b 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -69,6 +69,7 @@
 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 @@
 	[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_srq,
+	[IB_USER_VERBS_CMD_MODIFY_SRQ]    = ib_uverbs_modify_srq,
+	[IB_USER_VERBS_CMD_DESTROY_SRQ]   = ib_uverbs_destroy_srq,
 };
 
 static struct vfsmount *uverbs_event_mnt;
@@ -127,7 +131,14 @@
 		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) {
@@ -346,6 +357,13 @@
 				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)
 {