diff --git a/drivers/infiniband/core/uverbs_ioctl_cmd.c b/drivers/infiniband/core/uverbs_ioctl_cmd.c
index d38b7ec..57e9d76 100644
--- a/drivers/infiniband/core/uverbs_ioctl_cmd.c
+++ b/drivers/infiniband/core/uverbs_ioctl_cmd.c
@@ -31,6 +31,7 @@
  */
 
 #include <rdma/uverbs_ioctl_cmd.h>
+#include <rdma/ib_user_verbs.h>
 #include <linux/bug.h>
 
 #define IB_UVERBS_VENDOR_FLAG	0x8000
@@ -55,3 +56,42 @@ int uverbs_action_std_handle(struct ib_device *ib_dev,
 
 	return priv->handler(ib_dev, ucontext, &ctx[0], &ctx[1], priv->priv);
 }
+
+DECLARE_UVERBS_ATTR_CHAIN_SPEC(
+	uverbs_create_qp_spec,
+	UVERBS_ATTR_PTR_IN(CREATE_QP_CMD, sizeof(struct rdma_ioctl_create_qp)),
+	UVERBS_ATTR_PTR_OUT(CREATE_QP_RESP, sizeof(struct ib_uverbs_create_qp_resp)),
+	UVERBS_ATTR_IDR_IN(CREATE_QP_QP, UVERBS_TYPE_QP,
+			   UVERBS_IDR_ACCESS_NEW),
+	UVERBS_ATTR_IDR_IN(CREATE_QP_PD, UVERBS_TYPE_PD,
+			   UVERBS_IDR_ACCESS_READ),
+	UVERBS_ATTR_IDR_IN(CREATE_QP_RECV_CQ, UVERBS_TYPE_CQ,
+			   UVERBS_IDR_ACCESS_READ),
+	UVERBS_ATTR_IDR_IN(CREATE_QP_SEND_CQ, UVERBS_TYPE_CQ,
+			   UVERBS_IDR_ACCESS_READ));
+
+DECLARE_UVERBS_ATTR_CHAIN_SPEC(
+	uverbs_destroy_qp_spec,
+	UVERBS_ATTR_PTR_OUT(DESTROY_QP_RESP, sizeof(struct ib_uverbs_destroy_qp_resp)),
+	UVERBS_ATTR_IDR_IN(DESTROY_QP_QP, UVERBS_TYPE_QP,
+			   UVERBS_IDR_ACCESS_DESTROY));
+
+DECLARE_UVERBS_ATTR_CHAIN_SPEC(
+	uverbs_create_cq_spec,
+	UVERBS_ATTR_PTR_IN(CREATE_CQ_CMD, sizeof(struct rdma_create_cq)),
+	UVERBS_ATTR_PTR_OUT(CREATE_CQ_RESP, sizeof(struct ib_uverbs_create_cq_resp)));
+
+
+int uverbs_destroy_qp_handler(struct ib_device *ib_dev,
+			      struct ib_ucontext *ucontext,
+			      struct uverbs_attr_array *common,
+			      struct uverbs_attr_array *vendor,
+			      void *priv)
+{
+	/*
+	 * Implementation:
+	 * 1. Serialize to kAPI
+	 * 2. Call ib_dev with @vendor as vendor specific data
+	 */
+	return 0;
+}
diff --git a/drivers/infiniband/hw/ioctl-skel.c b/drivers/infiniband/hw/ioctl-skel.c
new file mode 100644
index 0000000..4bb646e
--- /dev/null
+++ b/drivers/infiniband/hw/ioctl-skel.c
@@ -0,0 +1,119 @@
+/* Vendor demo */
+
+#include <rdma/uverbs_ioctl_cmd.h>
+
+/*
+ * Vendor could have its own object model as well
+ * enum {
+ *	MLX5_VENDOR_TYPE_OBJ
+ * };
+ */
+
+struct mlx5_ib_create_qp_vendor_cmd {
+	__u64	buf_addr;
+	__u64	db_addr;
+	__u32	sq_wqe_count;
+	__u32	rq_wqe_count;
+	__u32	rq_wqe_shift;
+	__u32	flags;
+	__u32	uidx;
+	__u32	reserved0;
+	__u64	sq_buf_addr;
+};
+
+struct mlx5_ib_create_qp_vendor_resp {
+	__u32	uuar_index;
+};
+
+struct mlx5_ib_create_cq_vendor_cmd {
+	__u64	buf_addr;
+	__u64	db_addr;
+	__u32	cqe_size;
+	__u32	reserved;
+};
+
+struct mlx5_ib_create_cq_vendor_resp {
+	__u32	cqn;
+	__u32	reserved;
+};
+
+/* Could be per vendor handler */
+static int create_qp_handler(struct ib_device *ib_dev,
+			     struct ib_ucontext *ucontext,
+			     struct uverbs_attr_array *common,
+			     struct uverbs_attr_array *vendor,
+			     void *priv)
+{
+	/* Some smart things here */
+	return 0;
+}
+
+/* Could be per vendor handler */
+static int create_cq_handler(struct ib_device *ib_dev,
+			     struct ib_ucontext *ucontext,
+			     struct uverbs_attr_array *common,
+			     struct uverbs_attr_array *vendor,
+			     void *priv)
+{
+	/* Some smart things here */
+	return 0;
+}
+
+enum mlx5_qp_commands {
+	MLX5_QP_COMMAND_CREATE,
+	MLX5_QP_COMMAND_DESTROY
+	/* TODO: Other commands */
+};
+
+enum mlx5_cq_commands {
+	MLX5_CQ_COMMAND_CREATE,
+};
+
+enum mlx5_qp_create {
+	MLX5_CREATE_QP_VENDOR_CMD = IB_UVERBS_VENDOR_FLAG,
+	MLX5_CREATE_QP_VENDOR_RESP,
+};
+
+DECLARE_UVERBS_TYPE(mlx5_ib_qp,
+	UVERBS_ACTION(
+		MLX5_QP_COMMAND_CREATE, create_qp_handler, NULL, &uverbs_create_qp_spec,
+		&UVERBS_ATTR_CHAIN_SPEC(
+			UVERBS_ATTR_PTR_IN(MLX5_CREATE_QP_VENDOR_CMD,
+					   sizeof(struct mlx5_ib_create_qp_vendor_cmd)),
+			UVERBS_ATTR_PTR_OUT(MLX5_CREATE_QP_VENDOR_RESP,
+					    sizeof(struct mlx5_ib_create_qp_vendor_resp)),
+			/*
+			 * User could have its own objects and IDRs
+			 * UVERBS_ATTR_IDR_IN(MLX_CREATE_QP_VENDOR_OBJ,
+			 *		   UVERBS_COMMON_TYPE_QP, 0)
+			 */
+			),
+	),
+	UVERBS_ACTION(MLX5_QP_COMMAND_DESTROY, uverbs_destroy_qp_handler, NULL,
+		      &uverbs_destroy_qp_spec),
+);
+
+enum mlx5_cq_create {
+	MLX5_CREATE_CQ_VENDOR_CMD = IB_UVERBS_VENDOR_FLAG,
+	MLX5_CREATE_CQ_VENDOR_RESP,
+};
+
+struct uverbs_types objects = UVERBS_TYPES(
+	/* Decalre types by pointer */
+	UVERBS_TYPE(UVERBS_TYPE_QP, mlx5_ib_qp),
+	/* Types could only declared in-lined */
+	UVERBS_TYPE_ACTIONS(
+		UVERBS_TYPE_CQ,
+		UVERBS_ACTION(
+			MLX5_CQ_COMMAND_CREATE, create_cq_handler, NULL,
+			&uverbs_create_cq_spec,
+			&UVERBS_ATTR_CHAIN_SPEC(
+				UVERBS_ATTR_PTR_IN(MLX5_CREATE_CQ_VENDOR_CMD,
+						   sizeof(struct mlx5_ib_create_cq_vendor_cmd)),
+				UVERBS_ATTR_PTR_OUT(MLX5_CREATE_QP_VENDOR_RESP,
+						    sizeof(struct mlx5_ib_create_cq_vendor_resp)),
+			),
+		),
+	)
+);
+
diff --git a/include/rdma/uverbs_ioctl_cmd.h b/include/rdma/uverbs_ioctl_cmd.h
index 07cf6fa..ffb4d80 100644
--- a/include/rdma/uverbs_ioctl_cmd.h
+++ b/include/rdma/uverbs_ioctl_cmd.h
@@ -49,5 +49,40 @@ struct uverbs_action_std_handler {
 		       void *priv);
 	void *priv;
 };
+
+enum uverbs_common_types {
+	UVERBS_TYPE_PD,
+	UVERBS_TYPE_CQ,
+	UVERBS_TYPE_QP,
+};
+
+enum uverbs_create_qp_cmd_attr {
+	CREATE_QP_CMD,
+	CREATE_QP_RESP,
+	CREATE_QP_QP,
+	CREATE_QP_PD,
+	CREATE_QP_RECV_CQ,
+	CREATE_QP_SEND_CQ,
+};
+
+enum uverbs_destroy_qp_cmd_attr {
+	DESTROY_QP_RESP,
+	DESTROY_QP_QP,
+};
+
+enum uverbs_create_cq_cmd_attr {
+	CREATE_CQ_CMD,
+	CREATE_CQ_RESP,
+};
+
+extern const struct uverbs_attr_chain_spec uverbs_create_qp_spec;
+extern const struct uverbs_attr_chain_spec uverbs_destroy_qp_spec;
+extern const struct uverbs_attr_chain_spec uverbs_create_cq_spec;
+
+int uverbs_destroy_qp_handler(struct ib_device *ib_dev,
+			      struct ib_ucontext *ucontext,
+			      struct uverbs_attr_array *common,
+			      struct uverbs_attr_array *vendor,
+			      void *priv);
 #endif
 
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
index b6543d7..c6b2ef0 100644
--- a/include/uapi/rdma/ib_user_verbs.h
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -368,6 +368,14 @@ struct ib_uverbs_ex_create_cq {
 	__u32 reserved;
 };
 
+struct rdma_create_cq {
+	__u64 user_handle;
+	__u32 cqe;
+	__u32 comp_vector;
+	__s32 comp_channel;
+	__u32 flags;
+};
+
 struct ib_uverbs_create_cq_resp {
 	__u32 cq_handle;
 	__u32 cqe;
@@ -518,6 +526,17 @@ struct ib_uverbs_create_qp {
 	__u64 driver_data[0];
 };
 
+struct rdma_ioctl_create_qp
+{
+	__u32 max_send_wr;
+	__u32 max_recv_wr;
+	__u32 max_send_sge;
+	__u32 max_recv_sge;
+	__u32 max_inline_data;
+	__u8  sq_sig_all;
+	__u8  qp_type;
+};
+
 struct ib_uverbs_ex_create_qp {
 	__u64 user_handle;
 	__u32 pd_handle;
