rcq = cmd.recv_cq_handle == cmd.send_cq_handle ?
                scq : idr_read_cq(cmd.recv_cq_handle, file->ucontext, 1);
 
-       if (!pd || !scq || !rcq || (cmd.is_srq && !srq)) {
+       if (!pd || !scq || !rcq ||
+           (cmd.is_srq && (!srq || srq->srq_type != IB_SRQT_BASIC))) {
                ret = -EINVAL;
                goto err_put;
        }
        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)
+int __uverbs_create_xsrq(struct ib_uverbs_file *file,
+                        struct ib_uverbs_create_xsrq *cmd,
+                        struct ib_udata *udata)
 {
-       struct ib_uverbs_create_srq      cmd;
        struct ib_uverbs_create_srq_resp resp;
-       struct ib_udata                  udata;
-       struct ib_uevent_object         *obj;
+       struct ib_usrq_object           *obj;
        struct ib_pd                    *pd;
        struct ib_srq                   *srq;
+       struct ib_uobject               *uninitialized_var(xrcd_uobj);
        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);
-
        obj = kmalloc(sizeof *obj, GFP_KERNEL);
        if (!obj)
                return -ENOMEM;
 
-       init_uobj(&obj->uobject, cmd.user_handle, file->ucontext, &srq_lock_key);
-       down_write(&obj->uobject.mutex);
+       init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext, &srq_lock_key);
+       down_write(&obj->uevent.uobject.mutex);
 
-       pd  = idr_read_pd(cmd.pd_handle, file->ucontext);
+       pd  = idr_read_pd(cmd->pd_handle, file->ucontext);
        if (!pd) {
                ret = -EINVAL;
                goto err;
        }
 
+       if (cmd->srq_type == IB_SRQT_XRC) {
+               attr.ext.xrc.cq  = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+               if (!attr.ext.xrc.cq) {
+                       ret = -EINVAL;
+                       goto err_put_pd;
+               }
+
+               attr.ext.xrc.xrcd  = idr_read_xrcd(cmd->xrcd_handle, file->ucontext, &xrcd_uobj);
+               if (!attr.ext.xrc.xrcd) {
+                       ret = -EINVAL;
+                       goto err_put_cq;
+               }
+
+               obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object, uobject);
+               atomic_inc(&obj->uxrcd->refcnt);
+       }
+
        attr.event_handler  = ib_uverbs_srq_event_handler;
        attr.srq_context    = file;
-       attr.srq_type       = IB_SRQT_BASIC;
-       attr.attr.max_wr    = cmd.max_wr;
-       attr.attr.max_sge   = cmd.max_sge;
-       attr.attr.srq_limit = cmd.srq_limit;
+       attr.srq_type       = cmd->srq_type;
+       attr.attr.max_wr    = cmd->max_wr;
+       attr.attr.max_sge   = cmd->max_sge;
+       attr.attr.srq_limit = cmd->srq_limit;
 
-       obj->events_reported     = 0;
-       INIT_LIST_HEAD(&obj->event_list);
+       obj->uevent.events_reported = 0;
+       INIT_LIST_HEAD(&obj->uevent.event_list);
 
-       srq = pd->device->create_srq(pd, &attr, &udata);
+       srq = pd->device->create_srq(pd, &attr, udata);
        if (IS_ERR(srq)) {
                ret = PTR_ERR(srq);
                goto err_put;
        }
 
-       srq->device        = pd->device;
-       srq->pd            = pd;
-       srq->uobject       = &obj->uobject;
+       srq->device        = pd->device;
+       srq->pd            = pd;
+       srq->srq_type      = cmd->srq_type;
+       srq->uobject       = &obj->uevent.uobject;
        srq->event_handler = attr.event_handler;
        srq->srq_context   = attr.srq_context;
+
+       if (cmd->srq_type == IB_SRQT_XRC) {
+               srq->ext.xrc.cq   = attr.ext.xrc.cq;
+               srq->ext.xrc.xrcd = attr.ext.xrc.xrcd;
+               atomic_inc(&attr.ext.xrc.cq->usecnt);
+               atomic_inc(&attr.ext.xrc.xrcd->usecnt);
+       }
+
        atomic_inc(&pd->usecnt);
        atomic_set(&srq->usecnt, 0);
 
-       obj->uobject.object = srq;
-       ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+       obj->uevent.uobject.object = srq;
+       ret = idr_add_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
        if (ret)
                goto err_destroy;
 
        memset(&resp, 0, sizeof resp);
-       resp.srq_handle = obj->uobject.id;
+       resp.srq_handle = obj->uevent.uobject.id;
        resp.max_wr     = attr.attr.max_wr;
        resp.max_sge    = attr.attr.max_sge;
+       if (cmd->srq_type == IB_SRQT_XRC)
+               resp.srqn = srq->ext.xrc.srq_num;
 
-       if (copy_to_user((void __user *) (unsigned long) cmd.response,
+       if (copy_to_user((void __user *) (unsigned long) cmd->response,
                         &resp, sizeof resp)) {
                ret = -EFAULT;
                goto err_copy;
        }
 
+       if (cmd->srq_type == IB_SRQT_XRC) {
+               put_uobj_read(xrcd_uobj);
+               put_cq_read(attr.ext.xrc.cq);
+       }
        put_pd_read(pd);
 
        mutex_lock(&file->mutex);
-       list_add_tail(&obj->uobject.list, &file->ucontext->srq_list);
+       list_add_tail(&obj->uevent.uobject.list, &file->ucontext->srq_list);
        mutex_unlock(&file->mutex);
 
-       obj->uobject.live = 1;
+       obj->uevent.uobject.live = 1;
 
-       up_write(&obj->uobject.mutex);
+       up_write(&obj->uevent.uobject.mutex);
 
-       return in_len;
+       return 0;
 
 err_copy:
-       idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uobject);
+       idr_remove_uobj(&ib_uverbs_srq_idr, &obj->uevent.uobject);
 
 err_destroy:
        ib_destroy_srq(srq);
 
 err_put:
+       if (cmd->srq_type == IB_SRQT_XRC) {
+               atomic_dec(&obj->uxrcd->refcnt);
+               put_uobj_read(xrcd_uobj);
+       }
+
+err_put_cq:
+       if (cmd->srq_type == IB_SRQT_XRC)
+               put_cq_read(attr.ext.xrc.cq);
+
+err_put_pd:
        put_pd_read(pd);
 
 err:
-       put_uobj_write(&obj->uobject);
+       put_uobj_write(&obj->uevent.uobject);
        return ret;
 }
 
+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_xsrq     xcmd;
+       struct ib_uverbs_create_srq_resp resp;
+       struct ib_udata                  udata;
+       int ret;
+
+       if (out_len < sizeof resp)
+               return -ENOSPC;
+
+       if (copy_from_user(&cmd, buf, sizeof cmd))
+               return -EFAULT;
+
+       xcmd.response    = cmd.response;
+       xcmd.user_handle = cmd.user_handle;
+       xcmd.srq_type    = IB_SRQT_BASIC;
+       xcmd.pd_handle   = cmd.pd_handle;
+       xcmd.max_wr      = cmd.max_wr;
+       xcmd.max_sge     = cmd.max_sge;
+       xcmd.srq_limit   = cmd.srq_limit;
+
+       INIT_UDATA(&udata, buf + sizeof cmd,
+                  (unsigned long) cmd.response + sizeof resp,
+                  in_len - sizeof cmd, out_len - sizeof resp);
+
+       ret = __uverbs_create_xsrq(file, &xcmd, &udata);
+       if (ret)
+               return ret;
+
+       return in_len;
+}
+
+ssize_t ib_uverbs_create_xsrq(struct ib_uverbs_file *file,
+                             const char __user *buf, int in_len, int out_len)
+{
+       struct ib_uverbs_create_xsrq     cmd;
+       struct ib_uverbs_create_srq_resp resp;
+       struct ib_udata                  udata;
+       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);
+
+       ret = __uverbs_create_xsrq(file, &cmd, &udata);
+       if (ret)
+               return ret;
+
+       return in_len;
+}
+
 ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
                             const char __user *buf, int in_len,
                             int out_len)