linux-rdma.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface
@ 2018-06-17  9:59 Leon Romanovsky
  2018-06-17  9:59 ` [PATCH mlx5-next v2 01/20] net/mlx5_core: Prevent warns in dmesg upon firmware commands Leon Romanovsky
                   ` (20 more replies)
  0 siblings, 21 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Leon Romanovsky <leonro@mellanox.com>

Changelog:
v1->v2:
 * Rebase on top of v4.18-rc1
v0 -> v1:
 * Dropped few validation/debug patches from the KABI part as of Jason's comments.
 * Use kvmalloc/kvfree instead of kmalloc/kfree to prevent higher order allocation under user control.
 * Cleaned up a dependency of CONFIG_INFINIBAND_USER_ACCESS from the uverbs layer.
 * Moved to white list command mode.
 * Serialize access to DEVX object - odify/read new methods were added
   with the appropriate IDR lock.
 * Block DEVX on IB port as of SELinux.
 * Improve uverbs_cleanup_ucontext algorithm to support two objects from the same type.
 * Fix mlx5_ifc.h to use reserved_at_xxx.
 * Enforce devx_uid existence upon DEVX methods.

>From Yishai:
----------------------------------------------------------------------
This DEVX series enables direct access from the user space area to the
mlx5 device driver by using the KABI mechanism.

The main purpose here is to make the user space driver as independent as
possible from the kernel so that future device functionality and commands
can be activated with minimal to none kernel changes.

The series keeps the same level of user process security/isolation as
provided today by the kernel IB verbs by using a user id returned from
the firmware upon context creation.

This user id is put by the kernel code in all firmware command from the
DEVX interface so that the isolation/security will be enforced by the
firmware based on that id.

Below kernel services are exposed to let the above work:

1) Expose a DEVX object that represent some underlay firmware object,
the input command to create it is some raw data given by the user
application which should match the device specification.

2) Expose a UMEM DEVX object for user memory registration for DMA:
The driver provides an API to register user memory, getting as input the
user address, length and access flags, and provides to the user as output
an ID (UMEM ID) returned by the firmware to this registered memory.

The user will use that UMEM ID in device direct commands that use this
memory instead of the physical addresses list.

3) Expose device general command API:
The driver provides an API to issue some general command except than
create and destroy.

4) UAR mapping:
Returns a device UAR ID for a given user index by using the kernel
context information.

This is safe from security point of view as described in details in the
relevant patch in the series.

5) EQ mapping:
Returns the matching device EQN for a given user vector number via the
DEVX interface.

6) Process resources cleanup:
This is achieved by the existing kernel KABI logic, upon DEVX object
creation the kernel builds the FW destroy command inbox in the KABI
object and uses it upon cleanup.

7) Future device commands:
This will be supported by some general command type (create, destroy)
that the DEVX code embeds as part of its code and is going to be
used from now on by the firmware.

At the beginning of this series there are some KABI infra-structures
improvements and fixes to enable the above DEVX functionality in a
cleaner way.

More details appear as part of the commit logs of the series and as part
of the comments in the code itself.

Thanks

Leon Romanovsky (2):
  drm/i915: Move u64-to-ptr helpers to general header
  kernel.h: Reuse u64_to_ptr macro to cast __user pointers

Matan Barak (5):
  IB/uverbs: Export uverbs idr and fd types
  IB/uverbs: Refactor uverbs_finalize_objects
  IB/uverbs: Add PTR_IN attributes that are allocated/copied
    automatically
  IB/uverbs: Add a macro to define a type with no kernel known size
  IB/uverbs: Allow an empty namespace in ioctl() framework

Yishai Hadas (13):
  net/mlx5_core: Prevent warns in dmesg upon firmware commands
  IB/core: Improve uverbs_cleanup_ucontext algorithm
  net/mlx5: Expose DEVX ifc structures
  IB/mlx5: Introduce DEVX
  IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS
  IB: Expose ib_ucontext from a given ib_uverbs_file
  IB/mlx5: Add support for DEVX general command
  IB/mlx5: Add obj create and destroy functionality
  IB/mlx5: Add DEVX support for modify and query commands
  IB/mlx5: Add support for DEVX query UAR
  IB/mlx5: Add DEVX support for memory registration
  IB/mlx5: Add DEVX query EQN support
  IB/mlx5: Expose DEVX tree

 drivers/gpu/drm/i915/i915_utils.h                  |   12 +-
 drivers/infiniband/core/rdma_core.c                |  138 +--
 drivers/infiniband/core/rdma_core.h                |   10 +-
 drivers/infiniband/core/uverbs_ioctl.c             |  104 +-
 drivers/infiniband/core/uverbs_main.c              |    6 +
 drivers/infiniband/core/uverbs_std_types.c         |   26 +-
 .../infiniband/core/uverbs_std_types_counters.c    |    2 +-
 drivers/infiniband/core/uverbs_std_types_cq.c      |    2 +-
 drivers/infiniband/core/uverbs_std_types_dm.c      |    3 +-
 .../infiniband/core/uverbs_std_types_flow_action.c |    2 +-
 drivers/infiniband/core/uverbs_std_types_mr.c      |    3 +-
 drivers/infiniband/hw/mlx5/Makefile                |    1 +
 drivers/infiniband/hw/mlx5/devx.c                  | 1106 ++++++++++++++++++++
 drivers/infiniband/hw/mlx5/main.c                  |   31 +-
 drivers/infiniband/hw/mlx5/mlx5_ib.h               |   19 +
 drivers/infiniband/hw/mlx5/qp.c                    |    9 +-
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |   24 +-
 include/linux/kernel.h                             |   11 +-
 include/linux/mlx5/device.h                        |    3 +
 include/linux/mlx5/mlx5_ifc.h                      |   71 +-
 include/rdma/ib_verbs.h                            |    4 +-
 include/rdma/uverbs_ioctl.h                        |   27 +
 include/rdma/uverbs_named_ioctl.h                  |    4 +
 include/rdma/uverbs_std_types.h                    |    2 -
 include/rdma/uverbs_types.h                        |   11 +-
 include/uapi/rdma/mlx5-abi.h                       |    3 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h           |   73 ++
 27 files changed, 1548 insertions(+), 159 deletions(-)
 create mode 100644 drivers/infiniband/hw/mlx5/devx.c

^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH mlx5-next v2 01/20] net/mlx5_core: Prevent warns in dmesg upon firmware commands
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 02/20] drm/i915: Move u64-to-ptr helpers to general header Leon Romanovsky
                   ` (19 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

When DEVX is used application builds by itself the command mail box,
this patch prevents warns upon firmware commands as of invalid user
space usage.

In addition,
A failure in destroy_mkey command was changed to be printed only under
debug mode.

This prevents a redundant warn when a memory window was used
with rereg_mr and finally was some kernel cleanup as of reset
flow/process termination.

In that case this command might temporarily fails as part of the cleanup
but finally it expects to succeed.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 487388aed98f..b99d6df3905b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -677,7 +677,7 @@ struct mlx5_ifc_mbox_out_bits {
 
 struct mlx5_ifc_mbox_in_bits {
 	u8         opcode[0x10];
-	u8         reserved_at_10[0x10];
+	u8         uid[0x10];
 
 	u8         reserved_at_20[0x10];
 	u8         op_mod[0x10];
@@ -697,6 +697,7 @@ static int mlx5_cmd_check(struct mlx5_core_dev *dev, void *in, void *out)
 	u8  status;
 	u16 opcode;
 	u16 op_mod;
+	u16 uid;
 
 	mlx5_cmd_mbox_status(out, &status, &syndrome);
 	if (!status)
@@ -704,8 +705,18 @@ static int mlx5_cmd_check(struct mlx5_core_dev *dev, void *in, void *out)
 
 	opcode = MLX5_GET(mbox_in, in, opcode);
 	op_mod = MLX5_GET(mbox_in, in, op_mod);
+	uid    = MLX5_GET(mbox_in, in, uid);
 
-	mlx5_core_err(dev,
+	if (!uid && opcode != MLX5_CMD_OP_DESTROY_MKEY)
+		mlx5_core_err(dev,
+		      "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x)\n",
+		      mlx5_command_str(opcode),
+		      opcode, op_mod,
+		      cmd_status_str(status),
+		      status,
+		      syndrome);
+	else
+		mlx5_core_dbg(dev,
 		      "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x)\n",
 		      mlx5_command_str(opcode),
 		      opcode, op_mod,
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 02/20] drm/i915: Move u64-to-ptr helpers to general header
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
  2018-06-17  9:59 ` [PATCH mlx5-next v2 01/20] net/mlx5_core: Prevent warns in dmesg upon firmware commands Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 03/20] kernel.h: Reuse u64_to_ptr macro to cast __user pointers Leon Romanovsky
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Leon Romanovsky <leonro@mellanox.com>

The macro u64_to_ptr() and function ptr_to_u64() are useful enough
to be part of general header, so move them there and allow RDMA
subsystem reuse them.

Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/gpu/drm/i915/i915_utils.h | 12 ++----------
 include/linux/kernel.h            | 12 ++++++++++++
 2 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h
index 00165ad55fb3..2ffc43b97a5a 100644
--- a/drivers/gpu/drm/i915/i915_utils.h
+++ b/drivers/gpu/drm/i915/i915_utils.h
@@ -25,6 +25,8 @@
 #ifndef __I915_UTILS_H
 #define __I915_UTILS_H
 
+#include <linux/kernel.h>
+
 #undef WARN_ON
 /* Many gcc seem to no see through this and fall over :( */
 #if 0
@@ -102,16 +104,6 @@
 	__T;								\
 })
 
-static inline u64 ptr_to_u64(const void *ptr)
-{
-	return (uintptr_t)ptr;
-}
-
-#define u64_to_ptr(T, x) ({						\
-	typecheck(u64, x);						\
-	(T *)(uintptr_t)(x);						\
-})
-
 #define __mask_next_bit(mask) ({					\
 	int __idx = ffs(mask) - 1;					\
 	mask &= ~BIT(__idx);						\
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d23123238534..7d60a3472929 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -71,6 +71,18 @@
  */
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
 
+static inline u64 ptr_to_u64(const void *ptr)
+{
+	return (uintptr_t)ptr;
+}
+
+#define u64_to_ptr(T, x) (		\
+{					\
+	typecheck(u64, x);		\
+	(T *)(uintptr_t)(x);		\
+}					\
+)
+
 #define u64_to_user_ptr(x) (		\
 {					\
 	typecheck(u64, x);		\
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 03/20] kernel.h: Reuse u64_to_ptr macro to cast __user pointers
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
  2018-06-17  9:59 ` [PATCH mlx5-next v2 01/20] net/mlx5_core: Prevent warns in dmesg upon firmware commands Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 02/20] drm/i915: Move u64-to-ptr helpers to general header Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 04/20] IB/uverbs: Export uverbs idr and fd types Leon Romanovsky
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Leon Romanovsky <leonro@mellanox.com>

Redefine u64_to_user_ptr() macro to be implemented with u64_to_ptr().

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 include/linux/kernel.h | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 7d60a3472929..3012ae2f52f7 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -83,12 +83,7 @@ static inline u64 ptr_to_u64(const void *ptr)
 }					\
 )
 
-#define u64_to_user_ptr(x) (		\
-{					\
-	typecheck(u64, x);		\
-	(void __user *)(uintptr_t)x;	\
-}					\
-)
+#define u64_to_user_ptr(x)	u64_to_ptr(void __user, x)
 
 /*
  * This looks more complex than it should be. But we need to
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 04/20] IB/uverbs: Export uverbs idr and fd types
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (2 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 03/20] kernel.h: Reuse u64_to_ptr macro to cast __user pointers Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 05/20] IB/uverbs: Refactor uverbs_finalize_objects Leon Romanovsky
                   ` (16 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Matan Barak <matanb@mellanox.com>

As provider drivers could use UVERBS_ATTR_FD and UVERBS_ATTR_IDR macros
need to export them.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/rdma_core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index a6e904973ba8..8035a0a7564c 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -611,6 +611,7 @@ const struct uverbs_obj_type_class uverbs_idr_class = {
 	 */
 	.needs_kfree_rcu = true,
 };
+EXPORT_SYMBOL(uverbs_idr_class);
 
 static void _uverbs_close_fd(struct ib_uobject_file *uobj_file)
 {
@@ -719,6 +720,7 @@ const struct uverbs_obj_type_class uverbs_fd_class = {
 	.remove_commit = remove_commit_fd_uobject,
 	.needs_kfree_rcu = false,
 };
+EXPORT_SYMBOL(uverbs_fd_class);
 
 struct ib_uobject *uverbs_get_uobject_from_context(const struct uverbs_obj_type *type_attrs,
 						   struct ib_ucontext *ucontext,
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 05/20] IB/uverbs: Refactor uverbs_finalize_objects
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (3 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 04/20] IB/uverbs: Export uverbs idr and fd types Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically Leon Romanovsky
                   ` (15 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Matan Barak <matanb@mellanox.com>

uverbs_finalize_objects is currently used only to commit or abort
objects. Since we want to add automatic allocation/free of PTR_IN
attributes, moving it to uverbs_ioctl.c and renamit it to
uverbs_finalize_attrs.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/rdma_core.c    | 40 ---------------------
 drivers/infiniband/core/rdma_core.h    | 10 ++----
 drivers/infiniband/core/uverbs_ioctl.c | 64 +++++++++++++++++++++++++++-------
 3 files changed, 55 insertions(+), 59 deletions(-)

diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index 8035a0a7564c..df3c40533252 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -779,43 +779,3 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
 
 	return ret;
 }
-
-int uverbs_finalize_objects(struct uverbs_attr_bundle *attrs_bundle,
-			    struct uverbs_attr_spec_hash * const *spec_hash,
-			    size_t num,
-			    bool commit)
-{
-	unsigned int i;
-	int ret = 0;
-
-	for (i = 0; i < num; i++) {
-		struct uverbs_attr_bundle_hash *curr_bundle =
-			&attrs_bundle->hash[i];
-		const struct uverbs_attr_spec_hash *curr_spec_bucket =
-			spec_hash[i];
-		unsigned int j;
-
-		for (j = 0; j < curr_bundle->num_attrs; j++) {
-			struct uverbs_attr *attr;
-			const struct uverbs_attr_spec *spec;
-
-			if (!uverbs_attr_is_valid_in_hash(curr_bundle, j))
-				continue;
-
-			attr = &curr_bundle->attrs[j];
-			spec = &curr_spec_bucket->attrs[j];
-
-			if (spec->type == UVERBS_ATTR_TYPE_IDR ||
-			    spec->type == UVERBS_ATTR_TYPE_FD) {
-				int current_ret;
-
-				current_ret = uverbs_finalize_object(attr->obj_attr.uobject,
-								     spec->obj.access,
-								     commit);
-				if (!ret)
-					ret = current_ret;
-			}
-		}
-	}
-	return ret;
-}
diff --git a/drivers/infiniband/core/rdma_core.h b/drivers/infiniband/core/rdma_core.h
index 1efcf93238dd..a243cc2a59f7 100644
--- a/drivers/infiniband/core/rdma_core.h
+++ b/drivers/infiniband/core/rdma_core.h
@@ -94,9 +94,6 @@ struct ib_uobject *uverbs_get_uobject_from_context(const struct uverbs_obj_type
 						   struct ib_ucontext *ucontext,
 						   enum uverbs_obj_access access,
 						   int id);
-int uverbs_finalize_object(struct ib_uobject *uobj,
-			   enum uverbs_obj_access access,
-			   bool commit);
 /*
  * Note that certain finalize stages could return a status:
  *   (a) alloc_commit could return a failure if the object is committed at the
@@ -112,9 +109,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
  * function. For example, this could happen when we couldn't destroy an
  * object.
  */
-int uverbs_finalize_objects(struct uverbs_attr_bundle *attrs_bundle,
-			    struct uverbs_attr_spec_hash * const *spec_hash,
-			    size_t num,
-			    bool commit);
+int uverbs_finalize_object(struct ib_uobject *uobj,
+			   enum uverbs_obj_access access,
+			   bool commit);
 
 #endif /* RDMA_CORE_H */
diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 8d32c4ae368c..8cc3e8dad9b5 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -167,6 +167,46 @@ static int uverbs_process_attr(struct ib_device *ibdev,
 	return 0;
 }
 
+static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
+			  struct uverbs_attr_spec_hash * const *spec_hash,
+			  size_t num,
+			  bool commit)
+{
+	unsigned int i;
+	int ret = 0;
+
+	for (i = 0; i < num; i++) {
+		struct uverbs_attr_bundle_hash *curr_bundle =
+			&attrs_bundle->hash[i];
+		const struct uverbs_attr_spec_hash *curr_spec_bucket =
+			spec_hash[i];
+		unsigned int j;
+
+		for (j = 0; j < curr_bundle->num_attrs; j++) {
+			struct uverbs_attr *attr;
+			const struct uverbs_attr_spec *spec;
+
+			if (!uverbs_attr_is_valid_in_hash(curr_bundle, j))
+				continue;
+
+			attr = &curr_bundle->attrs[j];
+			spec = &curr_spec_bucket->attrs[j];
+
+			if (spec->type == UVERBS_ATTR_TYPE_IDR ||
+			    spec->type == UVERBS_ATTR_TYPE_FD) {
+				int current_ret;
+
+				current_ret = uverbs_finalize_object(attr->obj_attr.uobject,
+								     spec->obj.access,
+								     commit);
+				if (!ret)
+					ret = current_ret;
+			}
+		}
+	}
+	return ret;
+}
+
 static int uverbs_uattrs_process(struct ib_device *ibdev,
 				 struct ib_ucontext *ucontext,
 				 const struct ib_uverbs_attr *uattrs,
@@ -187,10 +227,10 @@ static int uverbs_uattrs_process(struct ib_device *ibdev,
 		ret = uverbs_ns_idx(&attr_id, method->num_buckets);
 		if (ret < 0) {
 			if (uattr->flags & UVERBS_ATTR_F_MANDATORY) {
-				uverbs_finalize_objects(attr_bundle,
-							method->attr_buckets,
-							num_given_buckets,
-							false);
+				uverbs_finalize_attrs(attr_bundle,
+						      method->attr_buckets,
+						      num_given_buckets,
+						      false);
 				return ret;
 			}
 			continue;
@@ -208,10 +248,10 @@ static int uverbs_uattrs_process(struct ib_device *ibdev,
 					  attr_spec_bucket, &attr_bundle->hash[ret],
 					  uattr_ptr++);
 		if (ret) {
-			uverbs_finalize_objects(attr_bundle,
-						method->attr_buckets,
-						num_given_buckets,
-						false);
+			uverbs_finalize_attrs(attr_bundle,
+					      method->attr_buckets,
+					      num_given_buckets,
+					      false);
 			return ret;
 		}
 	}
@@ -271,10 +311,10 @@ static int uverbs_handle_method(struct ib_uverbs_attr __user *uattr_ptr,
 
 	ret = method_spec->handler(ibdev, ufile, attr_bundle);
 cleanup:
-	finalize_ret = uverbs_finalize_objects(attr_bundle,
-					       method_spec->attr_buckets,
-					       attr_bundle->num_buckets,
-					       !ret);
+	finalize_ret = uverbs_finalize_attrs(attr_bundle,
+					     method_spec->attr_buckets,
+					     attr_bundle->num_buckets,
+					     !ret);
 
 	return ret ? ret : finalize_ret;
 }
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (4 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 05/20] IB/uverbs: Refactor uverbs_finalize_objects Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-18 20:48   ` Jason Gunthorpe
  2018-06-17  9:59 ` [PATCH rdma-next v2 07/20] IB/uverbs: Add a macro to define a type with no kernel known size Leon Romanovsky
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Matan Barak <matanb@mellanox.com>

Adding UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY flag to PTR_IN attributes.
By using this flag, the parse automatically allocates and copies the
user-space data. This data is accessible by using uverbs_attr_get_len
and uverbs_attr_get_alloced_ptr inline accessor functions from the
handler.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/uverbs_ioctl.c | 25 ++++++++++++++++++++++++-
 include/rdma/uverbs_ioctl.h            | 25 +++++++++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 8cc3e8dad9b5..ee15c9ca788b 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -114,7 +114,26 @@ static int uverbs_process_attr(struct ib_device *ibdev,
 		    uattr->attr_data.reserved)
 			return -EINVAL;
 
-		e->ptr_attr.data = uattr->data;
+		if (val_spec->flags & UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY &&
+		    uattr->len > sizeof(((struct ib_uverbs_attr *)0)->data)) {
+			int ret;
+			void *p;
+
+			p = kvmalloc(uattr->len, GFP_KERNEL);
+			if (!p)
+				return -ENOMEM;
+
+			e->ptr_attr.data = ptr_to_u64(p);
+
+			ret = copy_from_user(p, u64_to_user_ptr(uattr->data),
+					     uattr->len);
+			if (ret) {
+				kvfree(p);
+				return -EFAULT;
+			}
+		} else {
+			e->ptr_attr.data = uattr->data;
+		}
 		e->ptr_attr.len = uattr->len;
 		e->ptr_attr.flags = uattr->flags;
 		break;
@@ -201,6 +220,10 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 								     commit);
 				if (!ret)
 					ret = current_ret;
+			} else if (spec->type == UVERBS_ATTR_TYPE_PTR_IN &&
+				   spec->flags & UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY &&
+				   !uverbs_attr_ptr_is_inline(attr)) {
+				kvfree(u64_to_ptr(void, attr->ptr_attr.data));
 			}
 		}
 	}
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index bd6bba3a6e04..0e6f782727bd 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -65,6 +65,8 @@ enum {
 	UVERBS_ATTR_SPEC_F_MANDATORY	= 1U << 0,
 	/* Support extending attributes by length, validate all unknown size == zero  */
 	UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
+	/* Valid only for PTR_IN. Allocate and copy the data inside the parser */
+	UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY = 1U << 2,
 };
 
 /* Specification of a single attribute inside the ioctl message */
@@ -431,6 +433,17 @@ static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_att
 	return attr->obj_attr.uobject;
 }
 
+static inline int uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle,
+				      u16 idx)
+{
+	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
+
+	if (IS_ERR(attr))
+		return PTR_ERR(attr);
+
+	return attr->ptr_attr.len;
+}
+
 static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
 				 size_t idx, const void *from, size_t size)
 {
@@ -457,6 +470,18 @@ static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
 	return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
 }
 
+static inline void *uverbs_attr_get_alloced_ptr(const struct uverbs_attr_bundle *attrs_bundle,
+						u16 idx)
+{
+	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
+
+	if (IS_ERR(attr))
+		return (void *)attr;
+
+	return uverbs_attr_ptr_is_inline(attr) ? u64_to_ptr(void *, attr->ptr_attr.data) :
+		u64_to_ptr(void, attr->ptr_attr.data);
+}
+
 static inline int _uverbs_copy_from(void *to,
 				    const struct uverbs_attr_bundle *attrs_bundle,
 				    size_t idx,
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 07/20] IB/uverbs: Add a macro to define a type with no kernel known size
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (5 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 08/20] IB/uverbs: Allow an empty namespace in ioctl() framework Leon Romanovsky
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Matan Barak <matanb@mellanox.com>

Sometimes the uverbs uAPI  doesn't really care about the structure it gets
from user-space. All it wants to do is to allocate enough space and send
it to the hardware/provider driver. Adding a UVERBS_ATTR_MIN_SIZE that
could be used for this scenarios. We use USHRT_MAX as the kernel known
size to bypass any zero validations.

Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/uverbs_std_types.c | 4 ++--
 include/rdma/uverbs_ioctl.h                | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c
index b570acbd94af..0df0ac9c1de3 100644
--- a/drivers/infiniband/core/uverbs_std_types.c
+++ b/drivers/infiniband/core/uverbs_std_types.c
@@ -207,10 +207,10 @@ int uverbs_destroy_def_handler(struct ib_device *ib_dev,
  * spec.
  */
 const struct uverbs_attr_def uverbs_uhw_compat_in =
-	UVERBS_ATTR_PTR_IN_SZ(UVERBS_ATTR_UHW_IN, UVERBS_ATTR_SIZE(0, USHRT_MAX),
+	UVERBS_ATTR_PTR_IN_SZ(UVERBS_ATTR_UHW_IN, UVERBS_ATTR_MIN_SIZE(0),
 			      UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO));
 const struct uverbs_attr_def uverbs_uhw_compat_out =
-	UVERBS_ATTR_PTR_OUT_SZ(UVERBS_ATTR_UHW_OUT, UVERBS_ATTR_SIZE(0, USHRT_MAX),
+	UVERBS_ATTR_PTR_OUT_SZ(UVERBS_ATTR_UHW_OUT, UVERBS_ATTR_MIN_SIZE(0),
 			       UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO));
 
 void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata)
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index 0e6f782727bd..a57b58a0a59c 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -213,6 +213,8 @@ struct uverbs_object_tree_def {
 	.min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .len = sizeof(_type)
 #define UVERBS_ATTR_SIZE(_min_len, _len)			\
 	.min_len = _min_len, .len = _len
+#define UVERBS_ATTR_MIN_SIZE(_min_len)				\
+	UVERBS_ATTR_SIZE(_min_len, USHRT_MAX)
 
 /*
  * In new compiler, UVERBS_ATTR could be simplified by declaring it as
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 08/20] IB/uverbs: Allow an empty namespace in ioctl() framework
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (6 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 07/20] IB/uverbs: Add a macro to define a type with no kernel known size Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm Leon Romanovsky
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Matan Barak <matanb@mellanox.com>

The ioctl parser framework wrongly assumed that each namespace is
populated. This could lead to NULL dereferences. Fix the parser to
always check that a given namespace indeed exists.

Fixes: fac9658cabb9 ("IB/core: Add new ioctl interface")
Signed-off-by: Matan Barak <matanb@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/uverbs_ioctl.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index ee15c9ca788b..fb12e8ef7147 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -201,6 +201,9 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 			spec_hash[i];
 		unsigned int j;
 
+		if (!curr_spec_bucket)
+			continue;
+
 		for (j = 0; j < curr_bundle->num_attrs; j++) {
 			struct uverbs_attr *attr;
 			const struct uverbs_attr_spec *spec;
@@ -248,7 +251,7 @@ static int uverbs_uattrs_process(struct ib_device *ibdev,
 		struct uverbs_attr_spec_hash *attr_spec_bucket;
 
 		ret = uverbs_ns_idx(&attr_id, method->num_buckets);
-		if (ret < 0) {
+		if (ret < 0 || !method->attr_buckets[ret]) {
 			if (uattr->flags & UVERBS_ATTR_F_MANDATORY) {
 				uverbs_finalize_attrs(attr_bundle,
 						      method->attr_buckets,
@@ -291,6 +294,9 @@ static int uverbs_validate_kernel_mandatory(const struct uverbs_method_spec *met
 		struct uverbs_attr_spec_hash *attr_spec_bucket =
 			method_spec->attr_buckets[i];
 
+		if (!attr_spec_bucket)
+			continue;
+
 		if (!bitmap_subset(attr_spec_bucket->mandatory_attrs_bitmask,
 				   attr_bundle->hash[i].valid_bitmap,
 				   attr_spec_bucket->num_attrs))
@@ -404,7 +410,12 @@ static long ib_uverbs_cmd_verbs(struct ib_device *ib_dev,
 	 * filled at a later stage (uverbs_process_attr)
 	 */
 	for (i = 0; i < method_spec->num_buckets; i++) {
-		unsigned int curr_num_attrs = method_spec->attr_buckets[i]->num_attrs;
+		unsigned int curr_num_attrs;
+
+		if (!method_spec->attr_buckets[i])
+			continue;
+
+		curr_num_attrs = method_spec->attr_buckets[i]->num_attrs;
 
 		ctx->uverbs_attr_bundle->hash[i].attrs = curr_attr;
 		curr_attr += curr_num_attrs;
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (7 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 08/20] IB/uverbs: Allow an empty namespace in ioctl() framework Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17 19:51   ` Jason Gunthorpe
  2018-06-17  9:59 ` [PATCH mlx5-next v2 10/20] net/mlx5: Expose DEVX ifc structures Leon Romanovsky
                   ` (11 subsequent siblings)
  20 siblings, 1 reply; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Improve uverbs_cleanup_ucontext algorithm to work properly even when
there are two objects from the same type and one points to the other.
For that case to work the 'destroy_order' is not used any more as it's
static per type and can't support this use case.

Instead, the new algorithm iterates over the objects in a LIFO mode as
was before, at the end of each loop if were left objects that couldn't
be destroyed it re-iterates over them give another chance to destroy them
successfully.

If was one iteration that didn't cleanup any object the last iteration
will force the cleanup as was done before this change, this is coming to
prevent memory leaks even in that fatal case.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/rdma_core.c                | 96 ++++++++++++----------
 drivers/infiniband/core/uverbs_std_types.c         | 22 +++--
 .../infiniband/core/uverbs_std_types_counters.c    |  2 +-
 drivers/infiniband/core/uverbs_std_types_cq.c      |  2 +-
 drivers/infiniband/core/uverbs_std_types_dm.c      |  3 +-
 .../infiniband/core/uverbs_std_types_flow_action.c |  2 +-
 drivers/infiniband/core/uverbs_std_types_mr.c      |  3 +-
 include/rdma/ib_verbs.h                            |  2 +-
 include/rdma/uverbs_types.h                        | 11 +--
 9 files changed, 72 insertions(+), 71 deletions(-)

diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c
index df3c40533252..f4554de59659 100644
--- a/drivers/infiniband/core/rdma_core.c
+++ b/drivers/infiniband/core/rdma_core.c
@@ -645,61 +645,69 @@ void uverbs_close_fd(struct file *f)
 	kref_put(uverbs_file_ref, ib_uverbs_release_file);
 }
 
-void uverbs_cleanup_ucontext(struct ib_ucontext *ucontext, bool device_removed)
+static int __uverbs_cleanup_ucontext(struct ib_ucontext *ucontext,
+				    enum rdma_remove_reason reason)
 {
-	enum rdma_remove_reason reason = device_removed ?
-		RDMA_REMOVE_DRIVER_REMOVE : RDMA_REMOVE_CLOSE;
-	unsigned int cur_order = 0;
+	struct ib_uobject *obj, *next_obj;
+	int ret = -EINVAL;
+	int err = 0;
 
+	/*
+	 * This shouldn't run while executing other commands on this
+	 * context. Thus, the only thing we should take care of is
+	 * releasing a FD while traversing this list. The FD could be
+	 * closed and released from the _release fop of this FD.
+	 * In order to mitigate this, we add a lock.
+	 * We take and release the lock per traversal in order to let
+	 * other threads (which might still use the FDs) chance to run.
+	 */
+	mutex_lock(&ucontext->uobjects_lock);
 	ucontext->cleanup_reason = reason;
+	list_for_each_entry_safe(obj, next_obj, &ucontext->uobjects, list) {
+		/*
+		 * if we hit this WARN_ON, that means we are
+		 * racing with a lookup_get.
+		 */
+		WARN_ON(uverbs_try_lock_object(obj, true));
+		err = obj->type->type_class->remove_commit(obj, reason);
+		if (err) {
+			if (reason == RDMA_REMOVE_DESTROY) {
+				pr_debug("ib_uverbs: failed to remove uobject id %d err %d\n",
+					 obj->id, err);
+				atomic_set(&obj->usecnt, 0);
+				continue;
+			}
+
+			pr_warn("ib_uverbs: unable to remove uobject id %d err %d\n",
+				obj->id, err);
+		}
+
+		list_del(&obj->list);
+		/* put the ref we took when we created the object */
+		uverbs_uobject_put(obj);
+		ret = 0;
+	}
+	mutex_unlock(&ucontext->uobjects_lock);
+	return ret;
+}
+
+void uverbs_cleanup_ucontext(struct ib_ucontext *ucontext, bool device_removed)
+{
 	/*
 	 * Waits for all remove_commit and alloc_commit to finish. Logically, We
 	 * want to hold this forever as the context is going to be destroyed,
 	 * but we'll release it since it causes a "held lock freed" BUG message.
 	 */
 	down_write(&ucontext->cleanup_rwsem);
+	while (!list_empty(&ucontext->uobjects))
+		if (__uverbs_cleanup_ucontext(ucontext, RDMA_REMOVE_DESTROY))
+			/* No entry was cleaned-up successfully during this iteration */
+			break;
 
-	while (!list_empty(&ucontext->uobjects)) {
-		struct ib_uobject *obj, *next_obj;
-		unsigned int next_order = UINT_MAX;
+	if (!list_empty(&ucontext->uobjects))
+		__uverbs_cleanup_ucontext(ucontext, device_removed ?
+			RDMA_REMOVE_DRIVER_REMOVE : RDMA_REMOVE_CLOSE);
 
-		/*
-		 * This shouldn't run while executing other commands on this
-		 * context. Thus, the only thing we should take care of is
-		 * releasing a FD while traversing this list. The FD could be
-		 * closed and released from the _release fop of this FD.
-		 * In order to mitigate this, we add a lock.
-		 * We take and release the lock per order traversal in order
-		 * to let other threads (which might still use the FDs) chance
-		 * to run.
-		 */
-		mutex_lock(&ucontext->uobjects_lock);
-		list_for_each_entry_safe(obj, next_obj, &ucontext->uobjects,
-					 list) {
-			if (obj->type->destroy_order == cur_order) {
-				int ret;
-
-				/*
-				 * if we hit this WARN_ON, that means we are
-				 * racing with a lookup_get.
-				 */
-				WARN_ON(uverbs_try_lock_object(obj, true));
-				ret = obj->type->type_class->remove_commit(obj,
-									   reason);
-				list_del(&obj->list);
-				if (ret)
-					pr_warn("ib_uverbs: failed to remove uobject id %d order %u\n",
-						obj->id, cur_order);
-				/* put the ref we took when we created the object */
-				uverbs_uobject_put(obj);
-			} else {
-				next_order = min(next_order,
-						 obj->type->destroy_order);
-			}
-		}
-		mutex_unlock(&ucontext->uobjects_lock);
-		cur_order = next_order;
-	}
 	up_write(&ucontext->cleanup_rwsem);
 }
 
diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c
index 0df0ac9c1de3..0901b7877408 100644
--- a/drivers/infiniband/core/uverbs_std_types.c
+++ b/drivers/infiniband/core/uverbs_std_types.c
@@ -246,44 +246,42 @@ void create_udata(struct uverbs_attr_bundle *ctx, struct ib_udata *udata)
 }
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COMP_CHANNEL,
-			    &UVERBS_TYPE_ALLOC_FD(0,
-						  sizeof(struct ib_uverbs_completion_event_file),
+			    &UVERBS_TYPE_ALLOC_FD(sizeof(struct ib_uverbs_completion_event_file),
 						  uverbs_hot_unplug_completion_event_file,
 						  &uverbs_event_fops,
 						  "[infinibandevent]", O_RDONLY));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_QP,
-			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object), 0,
+			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uqp_object),
 						      uverbs_free_qp));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MW,
-			    &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_mw));
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_mw));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_SRQ,
-			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object), 0,
+			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
 						      uverbs_free_srq));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_AH,
-			    &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_ah));
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_ah));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_FLOW,
 			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uflow_object),
-						      0, uverbs_free_flow));
+						      uverbs_free_flow));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_WQ,
-			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object), 0,
+			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uwq_object),
 						      uverbs_free_wq));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_RWQ_IND_TBL,
-			    &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_rwq_ind_tbl));
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_rwq_ind_tbl));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_XRCD,
-			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object), 0,
+			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uxrcd_object),
 						      uverbs_free_xrcd));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_PD,
-			    /* 2 is used in order to free the PD after MRs */
-			    &UVERBS_TYPE_ALLOC_IDR(2, uverbs_free_pd));
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_pd));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_DEVICE, NULL);
 
diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c
index 03b182a684a6..e2d82b5ba732 100644
--- a/drivers/infiniband/core/uverbs_std_types_counters.c
+++ b/drivers/infiniband/core/uverbs_std_types_counters.c
@@ -150,7 +150,7 @@ static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_COUNTERS_READ,
 			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_COUNTERS,
-			    &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_counters),
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_counters),
 			    &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_CREATE),
 			    &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_DESTROY),
 			    &UVERBS_METHOD(UVERBS_METHOD_COUNTERS_READ));
diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c
index 3d293d01afea..278528f56f1f 100644
--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -201,7 +201,7 @@ static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_CQ_DESTROY,
 			     UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_CQ,
-			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object), 0,
+			    &UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_ucq_object),
 						      uverbs_free_cq),
 #if IS_ENABLED(CONFIG_INFINIBAND_EXP_LEGACY_VERBS_NEW_UAPI)
 			    &UVERBS_METHOD(UVERBS_METHOD_CQ_CREATE),
diff --git a/drivers/infiniband/core/uverbs_std_types_dm.c b/drivers/infiniband/core/uverbs_std_types_dm.c
index 8b681575b615..8fd976d30895 100644
--- a/drivers/infiniband/core/uverbs_std_types_dm.c
+++ b/drivers/infiniband/core/uverbs_std_types_dm.c
@@ -102,7 +102,6 @@ static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_DM_FREE,
 			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_DM,
-			    /* 1 is used in order to free the DM after MRs */
-			    &UVERBS_TYPE_ALLOC_IDR(1, uverbs_free_dm),
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_dm),
 			    &UVERBS_METHOD(UVERBS_METHOD_DM_ALLOC),
 			    &UVERBS_METHOD(UVERBS_METHOD_DM_FREE));
diff --git a/drivers/infiniband/core/uverbs_std_types_flow_action.c b/drivers/infiniband/core/uverbs_std_types_flow_action.c
index a7be51cf2e42..0cc15f8ee455 100644
--- a/drivers/infiniband/core/uverbs_std_types_flow_action.c
+++ b/drivers/infiniband/core/uverbs_std_types_flow_action.c
@@ -428,7 +428,7 @@ static DECLARE_UVERBS_NAMED_METHOD_WITH_HANDLER(UVERBS_METHOD_FLOW_ACTION_DESTRO
 			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_FLOW_ACTION,
-			    &UVERBS_TYPE_ALLOC_IDR(0, uverbs_free_flow_action),
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_flow_action),
 			    &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE),
 			    &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_DESTROY),
 			    &UVERBS_METHOD(UVERBS_METHOD_FLOW_ACTION_ESP_MODIFY));
diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c b/drivers/infiniband/core/uverbs_std_types_mr.c
index 68f7cadf088f..d7f7ba3802af 100644
--- a/drivers/infiniband/core/uverbs_std_types_mr.c
+++ b/drivers/infiniband/core/uverbs_std_types_mr.c
@@ -142,6 +142,5 @@ static DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_DM_MR_REG,
 			     UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
 DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_MR,
-			    /* 1 is used in order to free the MR after all the MWs */
-			    &UVERBS_TYPE_ALLOC_IDR(1, uverbs_free_mr),
+			    &UVERBS_TYPE_ALLOC_IDR(uverbs_free_mr),
 			    &UVERBS_METHOD(UVERBS_METHOD_DM_MR_REG));
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 4c6241bc2039..152b5907c864 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1473,7 +1473,7 @@ struct ib_fmr_attr {
 struct ib_umem;
 
 enum rdma_remove_reason {
-	/* Userspace requested uobject deletion. Call could fail */
+	/* Userspace requested uobject deletion or initial try to remove uobject via cleanup. Call could fail */
 	RDMA_REMOVE_DESTROY,
 	/* Context deletion. This call should delete the actual object itself */
 	RDMA_REMOVE_CLOSE,
diff --git a/include/rdma/uverbs_types.h b/include/rdma/uverbs_types.h
index cc04ec65588d..175495d1b0b8 100644
--- a/include/rdma/uverbs_types.h
+++ b/include/rdma/uverbs_types.h
@@ -93,7 +93,6 @@ struct uverbs_obj_type_class {
 struct uverbs_obj_type {
 	const struct uverbs_obj_type_class * const type_class;
 	size_t	     obj_size;
-	unsigned int destroy_order;
 };
 
 /*
@@ -152,10 +151,9 @@ extern const struct uverbs_obj_type_class uverbs_fd_class;
 
 #define UVERBS_BUILD_BUG_ON(cond) (sizeof(char[1 - 2 * !!(cond)]) -	\
 				   sizeof(char))
-#define UVERBS_TYPE_ALLOC_FD(_order, _obj_size, _context_closed, _fops, _name, _flags)\
+#define UVERBS_TYPE_ALLOC_FD(_obj_size, _context_closed, _fops, _name, _flags)\
 	((&((const struct uverbs_obj_fd_type)				\
 	 {.type = {							\
-		.destroy_order = _order,				\
 		.type_class = &uverbs_fd_class,				\
 		.obj_size = (_obj_size) +				\
 			UVERBS_BUILD_BUG_ON((_obj_size) < sizeof(struct ib_uobject_file)), \
@@ -164,18 +162,17 @@ extern const struct uverbs_obj_type_class uverbs_fd_class;
 	 .fops = _fops,							\
 	 .name = _name,							\
 	 .flags = _flags}))->type)
-#define UVERBS_TYPE_ALLOC_IDR_SZ(_size, _order, _destroy_object)	\
+#define UVERBS_TYPE_ALLOC_IDR_SZ(_size, _destroy_object)	\
 	((&((const struct uverbs_obj_idr_type)				\
 	 {.type = {							\
-		.destroy_order = _order,				\
 		.type_class = &uverbs_idr_class,			\
 		.obj_size = (_size) +					\
 			UVERBS_BUILD_BUG_ON((_size) <			\
 					    sizeof(struct ib_uobject))	\
 	 },								\
 	 .destroy_object = _destroy_object,}))->type)
-#define UVERBS_TYPE_ALLOC_IDR(_order, _destroy_object)			\
-	 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uobject), _order,	\
+#define UVERBS_TYPE_ALLOC_IDR(_destroy_object)			\
+	 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_uobject),	\
 				  _destroy_object)
 
 #endif
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH mlx5-next v2 10/20] net/mlx5: Expose DEVX ifc structures
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (8 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH mlx5-next v2 11/20] IB/mlx5: Introduce DEVX Leon Romanovsky
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

This patch updates the mlx5_ifc structures with the following:
- Expose general command header in/out format.
- Expose user context format.
- Expose umem format.

Downstream patches from this series will use this stuff.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 include/linux/mlx5/mlx5_ifc.h | 52 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 27134c4fcb76..78d4993a2920 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -9115,4 +9115,56 @@ struct mlx5_ifc_dealloc_memic_out_bits {
 	u8         reserved_at_40[0x40];
 };
 
+struct mlx5_ifc_general_obj_in_cmd_hdr_bits {
+	u8         opcode[0x10];
+	u8         uid[0x10];
+
+	u8         reserved_at_20[0x10];
+	u8         obj_type[0x10];
+
+	u8         obj_id[0x20];
+
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_general_obj_out_cmd_hdr_bits {
+	u8         status[0x8];
+	u8         reserved_at_8[0x18];
+
+	u8         syndrome[0x20];
+
+	u8         obj_id[0x20];
+
+	u8         reserved_at_60[0x20];
+};
+
+struct mlx5_ifc_umem_bits {
+	u8         modify_field_select[0x40];
+
+	u8         reserved_at_40[0x5b];
+	u8         log_page_size[0x5];
+
+	u8         page_offset[0x20];
+
+	u8         num_of_mtt[0x40];
+
+	struct mlx5_ifc_mtt_bits  mtt[0];
+};
+
+struct mlx5_ifc_uctx_bits {
+	u8         modify_field_select[0x40];
+
+	u8         reserved_at_40[0x1c0];
+};
+
+struct mlx5_ifc_create_umem_in_bits {
+	struct mlx5_ifc_general_obj_in_cmd_hdr_bits   hdr;
+	struct mlx5_ifc_umem_bits                     umem;
+};
+
+struct mlx5_ifc_create_uctx_in_bits {
+	struct mlx5_ifc_general_obj_in_cmd_hdr_bits   hdr;
+	struct mlx5_ifc_uctx_bits                     uctx;
+};
+
 #endif /* MLX5_IFC_H */
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH mlx5-next v2 11/20] IB/mlx5: Introduce DEVX
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (9 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH mlx5-next v2 10/20] net/mlx5: Expose DEVX ifc structures Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 12/20] IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS Leon Romanovsky
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Introduce DEVX to enable direct device commands in downstream patches
from this series.

In that mode of work the firmware manages the isolation between
processes' resources and as such a DEVX user id is created and assigned
to the given user context upon allocation request.

A capability check is done to make sure that this feature is really
supported by the firmware prior to creating the DEVX user id.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/Makefile           |  1 +
 drivers/infiniband/hw/mlx5/devx.c             | 58 +++++++++++++++++++++++++++
 drivers/infiniband/hw/mlx5/main.c             | 24 +++++++++--
 drivers/infiniband/hw/mlx5/mlx5_ib.h          | 13 ++++++
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c |  4 ++
 include/linux/mlx5/device.h                   |  3 ++
 include/linux/mlx5/mlx5_ifc.h                 | 15 ++++++-
 include/uapi/rdma/mlx5-abi.h                  |  3 ++
 8 files changed, 117 insertions(+), 4 deletions(-)
 create mode 100644 drivers/infiniband/hw/mlx5/devx.c

diff --git a/drivers/infiniband/hw/mlx5/Makefile b/drivers/infiniband/hw/mlx5/Makefile
index d42b922bede8..577e4c418bae 100644
--- a/drivers/infiniband/hw/mlx5/Makefile
+++ b/drivers/infiniband/hw/mlx5/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_MLX5_INFINIBAND)	+= mlx5_ib.o
 mlx5_ib-y :=	main.o cq.o doorbell.o qp.o mem.o srq.o mr.o ah.o mad.o gsi.o ib_virt.o cmd.o cong.o
 mlx5_ib-$(CONFIG_INFINIBAND_ON_DEMAND_PAGING) += odp.o
 mlx5_ib-$(CONFIG_MLX5_ESWITCH) += ib_rep.o
+mlx5_ib-$(CONFIG_INFINIBAND_USER_ACCESS) += devx.o
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
new file mode 100644
index 000000000000..775448910ad1
--- /dev/null
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/*
+ * Copyright (c) 2018, Mellanox Technologies inc.  All rights reserved.
+ */
+
+#include <rdma/ib_user_verbs.h>
+#include <rdma/ib_verbs.h>
+#include <rdma/uverbs_types.h>
+#include <rdma/uverbs_ioctl.h>
+#include <rdma/mlx5_user_ioctl_cmds.h>
+#include <rdma/ib_umem.h>
+#include <linux/mlx5/driver.h>
+#include <linux/mlx5/fs.h>
+#include "mlx5_ib.h"
+
+int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
+{
+	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
+	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+	u64 general_obj_types;
+	void *uctx;
+	void *hdr;
+	int err;
+
+	uctx = MLX5_ADDR_OF(create_uctx_in, in, uctx);
+	hdr = MLX5_ADDR_OF(create_uctx_in, in, hdr);
+
+	general_obj_types = MLX5_CAP_GEN_64(dev->mdev, general_obj_types);
+	if (!(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UCTX) ||
+	    !(general_obj_types & MLX5_GENERAL_OBJ_TYPES_CAP_UMEM))
+		return -EINVAL;
+
+	if (!capable(CAP_NET_RAW))
+		return -EPERM;
+
+	MLX5_SET(general_obj_in_cmd_hdr, hdr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+	MLX5_SET(general_obj_in_cmd_hdr, hdr, obj_type, MLX5_OBJ_TYPE_UCTX);
+
+	err = mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
+	if (err)
+		return err;
+
+	context->devx_uid = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+	return 0;
+}
+
+void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
+			  struct mlx5_ib_ucontext *context)
+{
+	u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {0};
+	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
+
+	MLX5_SET(general_obj_in_cmd_hdr, in, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
+	MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, MLX5_OBJ_TYPE_UCTX);
+	MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, context->devx_uid);
+
+	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
+}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index e52dd21519b4..430a9e36d392 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -1676,8 +1676,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
 	if (err)
 		return ERR_PTR(err);
 
-	if (req.flags)
-		return ERR_PTR(-EINVAL);
+	if (req.flags & ~MLX5_IB_ALLOC_UCTX_DEVX)
+		return ERR_PTR(-EOPNOTSUPP);
 
 	if (req.comp_mask || req.reserved0 || req.reserved1 || req.reserved2)
 		return ERR_PTR(-EOPNOTSUPP);
@@ -1761,6 +1761,18 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
 			goto out_uars;
 	}
 
+	if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {
+		/* Block DEVX on Infiniband as of SELinux */
+		if (mlx5_ib_port_link_layer(ibdev, 1) != IB_LINK_LAYER_ETHERNET) {
+			err = -EPERM;
+			goto out_td;
+		}
+
+		err = mlx5_ib_devx_create(dev, context);
+		if (err)
+			goto out_td;
+	}
+
 	INIT_LIST_HEAD(&context->vma_private_list);
 	mutex_init(&context->vma_private_list_mutex);
 	INIT_LIST_HEAD(&context->db_page_list);
@@ -1821,7 +1833,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
 
 	err = ib_copy_to_udata(udata, &resp, resp.response_length);
 	if (err)
-		goto out_td;
+		goto out_mdev;
 
 	bfregi->ver = ver;
 	bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs;
@@ -1831,6 +1843,9 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
 
 	return &context->ibucontext;
 
+out_mdev:
+	if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
+		mlx5_ib_devx_destroy(dev, context);
 out_td:
 	if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
 		mlx5_ib_dealloc_transport_domain(dev, context->tdn);
@@ -1856,6 +1871,9 @@ static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
 	struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
 	struct mlx5_bfreg_info *bfregi;
 
+	if (context->devx_uid)
+		mlx5_ib_devx_destroy(dev, context);
+
 	bfregi = &context->bfregi;
 	if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
 		mlx5_ib_dealloc_transport_domain(dev, context->tdn);
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index d89c8fe626f6..5e8abd8bcd71 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -143,6 +143,7 @@ struct mlx5_ib_ucontext {
 
 	u64			lib_caps;
 	DECLARE_BITMAP(dm_pages, MLX5_MAX_MEMIC_PAGES);
+	u16			devx_uid;
 };
 
 static inline struct mlx5_ib_ucontext *to_mucontext(struct ib_ucontext *ibucontext)
@@ -1217,6 +1218,18 @@ struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *dev,
 void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *dev,
 				  u8 port_num);
 
+#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
+int mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
+			struct mlx5_ib_ucontext *context);
+void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
+			  struct mlx5_ib_ucontext *context);
+#else
+static inline int
+mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
+		    struct mlx5_ib_ucontext *context) { return -EOPNOTSUPP; };
+static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
+					struct mlx5_ib_ucontext *context) {}
+#endif
 static inline void init_query_mad(struct ib_smp *mad)
 {
 	mad->base_version  = 1;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index b99d6df3905b..d07f24de8fa3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -310,6 +310,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER:
 	case MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT:
 	case MLX5_CMD_OP_FPGA_DESTROY_QP:
+	case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT:
 		return MLX5_CMD_STAT_OK;
 
 	case MLX5_CMD_OP_QUERY_HCA_CAP:
@@ -427,6 +428,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_FPGA_MODIFY_QP:
 	case MLX5_CMD_OP_FPGA_QUERY_QP:
 	case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS:
+	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
 		*status = MLX5_DRIVER_STATUS_ABORTED;
 		*synd = MLX5_DRIVER_SYND;
 		return -EIO;
@@ -599,6 +601,8 @@ const char *mlx5_command_str(int command)
 	MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP);
 	MLX5_COMMAND_STR_CASE(FPGA_QUERY_QP_COUNTERS);
 	MLX5_COMMAND_STR_CASE(FPGA_DESTROY_QP);
+	MLX5_COMMAND_STR_CASE(CREATE_GENERAL_OBJECT);
+	MLX5_COMMAND_STR_CASE(DESTROY_GENERAL_OBJECT);
 	default: return "unknown command opcode";
 	}
 }
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 02f72ebf31a7..f8671c0a43aa 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -1071,6 +1071,9 @@ enum mlx5_qcam_feature_groups {
 #define MLX5_CAP_GEN(mdev, cap) \
 	MLX5_GET(cmd_hca_cap, mdev->caps.hca_cur[MLX5_CAP_GENERAL], cap)
 
+#define MLX5_CAP_GEN_64(mdev, cap) \
+	MLX5_GET64(cmd_hca_cap, mdev->caps.hca_cur[MLX5_CAP_GENERAL], cap)
+
 #define MLX5_CAP_GEN_MAX(mdev, cap) \
 	MLX5_GET(cmd_hca_cap, mdev->caps.hca_max[MLX5_CAP_GENERAL], cap)
 
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 78d4993a2920..f810772e80c0 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -75,6 +75,15 @@ enum {
 	MLX5_SET_HCA_CAP_OP_MOD_ATOMIC                = 0x3,
 };
 
+enum {
+	MLX5_GENERAL_OBJ_TYPES_CAP_UCTX = (1ULL << 4),
+	MLX5_GENERAL_OBJ_TYPES_CAP_UMEM = (1ULL << 5),
+};
+
+enum {
+	MLX5_OBJ_TYPE_UCTX = 0x0004,
+};
+
 enum {
 	MLX5_CMD_OP_QUERY_HCA_CAP                 = 0x100,
 	MLX5_CMD_OP_QUERY_ADAPTER                 = 0x101,
@@ -242,6 +251,8 @@ enum {
 	MLX5_CMD_OP_FPGA_QUERY_QP                 = 0x962,
 	MLX5_CMD_OP_FPGA_DESTROY_QP               = 0x963,
 	MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS        = 0x964,
+	MLX5_CMD_OP_CREATE_GENERAL_OBJECT         = 0xa00,
+	MLX5_CMD_OP_DESTROY_GENERAL_OBJECT        = 0xa03,
 	MLX5_CMD_OP_MAX
 };
 
@@ -1113,7 +1124,9 @@ struct mlx5_ifc_cmd_hca_cap_bits {
 	u8         reserved_at_3f8[0x3];
 	u8         log_max_current_uc_list[0x5];
 
-	u8         reserved_at_400[0x80];
+	u8         general_obj_types[0x40];
+
+	u8         reserved_at_440[0x40];
 
 	u8         reserved_at_480[0x3];
 	u8         log_max_l2_table[0x5];
diff --git a/include/uapi/rdma/mlx5-abi.h b/include/uapi/rdma/mlx5-abi.h
index 8daec1fa49cf..5d591ff28139 100644
--- a/include/uapi/rdma/mlx5-abi.h
+++ b/include/uapi/rdma/mlx5-abi.h
@@ -76,6 +76,9 @@ enum mlx5_lib_caps {
 	MLX5_LIB_CAP_4K_UAR	= (__u64)1 << 0,
 };
 
+enum mlx5_ib_alloc_uctx_v2_flags {
+	MLX5_IB_ALLOC_UCTX_DEVX	= 1 << 0,
+};
 struct mlx5_ib_alloc_ucontext_req_v2 {
 	__u32	total_num_bfregs;
 	__u32	num_low_latency_bfregs;
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 12/20] IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (10 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH mlx5-next v2 11/20] IB/mlx5: Introduce DEVX Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17  9:59 ` [PATCH rdma-next v2 13/20] IB: Expose ib_ucontext from a given ib_uverbs_file Leon Romanovsky
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Introduce a new macro to be used for global methods on a singleton
object.

This macros sets internally the type_attrs to be NULL as such an object
can't be created.

Downstream patches from this series will use this macro.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 include/rdma/uverbs_named_ioctl.h | 4 ++++
 include/rdma/uverbs_std_types.h   | 2 --
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/rdma/uverbs_named_ioctl.h b/include/rdma/uverbs_named_ioctl.h
index c5bb4ebdb0b0..228421f2a427 100644
--- a/include/rdma/uverbs_named_ioctl.h
+++ b/include/rdma/uverbs_named_ioctl.h
@@ -43,6 +43,7 @@
 #define _UVERBS_NAME(x, y)	_UVERBS_PASTE(x, y)
 #define UVERBS_METHOD(id)	_UVERBS_NAME(UVERBS_MODULE_NAME, _method_##id)
 #define UVERBS_HANDLER(id)	_UVERBS_NAME(UVERBS_MODULE_NAME, _handler_##id)
+#define UVERBS_OBJECT(id)	_UVERBS_NAME(UVERBS_MOUDLE_NAME, _object_##id)
 
 #define DECLARE_UVERBS_NAMED_METHOD(id, ...)	\
 	DECLARE_UVERBS_METHOD(UVERBS_METHOD(id), id, UVERBS_HANDLER(id), ##__VA_ARGS__)
@@ -56,6 +57,9 @@
 #define DECLARE_UVERBS_NAMED_OBJECT(id, ...)	\
 	DECLARE_UVERBS_OBJECT(UVERBS_OBJECT(id), id, ##__VA_ARGS__)
 
+#define DECLARE_UVERBS_GLOBAL_METHODS(_name, ...)	\
+	DECLARE_UVERBS_NAMED_OBJECT(_name, NULL, ##__VA_ARGS__)
+
 #define _UVERBS_COMP_NAME(x, y, z) _UVERBS_NAME(_UVERBS_NAME(x, y), z)
 
 #define UVERBS_NO_OVERRIDE	NULL
diff --git a/include/rdma/uverbs_std_types.h b/include/rdma/uverbs_std_types.h
index 9d56cdb84655..4c151b67fb6d 100644
--- a/include/rdma/uverbs_std_types.h
+++ b/include/rdma/uverbs_std_types.h
@@ -37,8 +37,6 @@
 #include <rdma/uverbs_ioctl.h>
 #include <rdma/ib_user_ioctl_verbs.h>
 
-#define UVERBS_OBJECT(id)	uverbs_object_##id
-
 #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
 const struct uverbs_object_tree_def *uverbs_default_get_objects(void);
 #else
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 13/20] IB: Expose ib_ucontext from a given ib_uverbs_file
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (11 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 12/20] IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS Leon Romanovsky
@ 2018-06-17  9:59 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH rdma-next v2 14/20] IB/mlx5: Add support for DEVX general command Leon Romanovsky
                   ` (7 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17  9:59 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Drivers that use the IOCTL API may have the ib_uverbs_file and need a
way to get the related ib_ucontext from it, this is enabled by this
patch.

Downstream patches from this series will use it.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/uverbs_main.c | 6 ++++++
 include/rdma/ib_verbs.h               | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 3ae2339dd27a..f5f4bfb59705 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -138,6 +138,12 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
 static void ib_uverbs_add_one(struct ib_device *device);
 static void ib_uverbs_remove_one(struct ib_device *device, void *client_data);
 
+struct ib_ucontext *ib_uverbs_get_ucontext(struct ib_uverbs_file *ufile)
+{
+	return ufile->ucontext;
+}
+EXPORT_SYMBOL(ib_uverbs_get_ucontext);
+
 int uverbs_dealloc_mw(struct ib_mw *mw)
 {
 	struct ib_pd *pd = mw->pd;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 152b5907c864..1b30520c8c28 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -4107,4 +4107,6 @@ ib_get_vector_affinity(struct ib_device *device, int comp_vector)
  */
 void rdma_roce_rescan_device(struct ib_device *ibdev);
 
+struct ib_ucontext *ib_uverbs_get_ucontext(struct ib_uverbs_file *ufile);
+
 #endif /* IB_VERBS_H */
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 14/20] IB/mlx5: Add support for DEVX general command
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (12 preceding siblings ...)
  2018-06-17  9:59 ` [PATCH rdma-next v2 13/20] IB: Expose ib_ucontext from a given ib_uverbs_file Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH rdma-next v2 15/20] IB/mlx5: Add obj create and destroy functionality Leon Romanovsky
                   ` (6 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Add support to run general firmware command via the DEVX interface.

A command that works on some object (e.g. CQ, WQ, etc.) will be added
in next patches while maintaining the required object lock.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c        | 87 ++++++++++++++++++++++++++++++++
 include/uapi/rdma/mlx5_user_ioctl_cmds.h | 13 +++++
 2 files changed, 100 insertions(+)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 775448910ad1..9fca6541a175 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -13,6 +13,14 @@
 #include <linux/mlx5/fs.h>
 #include "mlx5_ib.h"
 
+#define UVERBS_MODULE_NAME mlx5_ib
+#include <rdma/uverbs_named_ioctl.h>
+
+static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
+{
+	return to_mucontext(ib_uverbs_get_ucontext(file));
+}
+
 int mlx5_ib_devx_create(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
 {
 	u32 in[MLX5_ST_SZ_DW(create_uctx_in)] = {0};
@@ -56,3 +64,82 @@ void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 
 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
 }
+
+static bool devx_is_general_cmd(void *in)
+{
+	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+
+	switch (opcode) {
+	case MLX5_CMD_OP_QUERY_HCA_CAP:
+	case MLX5_CMD_OP_QUERY_VPORT_STATE:
+	case MLX5_CMD_OP_QUERY_ADAPTER:
+	case MLX5_CMD_OP_QUERY_ISSI:
+	case MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT:
+	case MLX5_CMD_OP_QUERY_ROCE_ADDRESS:
+	case MLX5_CMD_OP_QUERY_VNIC_ENV:
+	case MLX5_CMD_OP_QUERY_VPORT_COUNTER:
+	case MLX5_CMD_OP_GET_DROPPED_PACKET_LOG:
+	case MLX5_CMD_OP_NOP:
+	case MLX5_CMD_OP_QUERY_CONG_STATUS:
+	case MLX5_CMD_OP_QUERY_CONG_PARAMS:
+	case MLX5_CMD_OP_QUERY_CONG_STATISTICS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(struct ib_device *ib_dev,
+				  struct ib_uverbs_file *file,
+				  struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN);
+	int cmd_out_len = uverbs_attr_get_len(attrs,
+					MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT);
+	void *cmd_out;
+	int err;
+
+	if (!c->devx_uid)
+		return -EPERM;
+
+	/* Only white list of some general HCA commands are allowed for this method. */
+	if (!devx_is_general_cmd(cmd_in))
+		return -EINVAL;
+
+	cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
+	if (!cmd_out)
+		return -ENOMEM;
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+	err = mlx5_cmd_exec(dev->mdev, cmd_in,
+			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_IN),
+			    cmd_out, cmd_out_len);
+	if (err)
+		goto other_cmd_free;
+
+	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT, cmd_out, cmd_out_len);
+
+other_cmd_free:
+	kvfree(cmd_out);
+	return err;
+}
+
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
+	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
+			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
+			       UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
+					UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
+	&UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
+				UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
+				UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO))
+);
+
+static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER));
+
+static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
+	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX));
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index f7d685ef2d1f..0b456fa91bb4 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -45,4 +45,17 @@ enum mlx5_ib_alloc_dm_attrs {
 	MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
 };
 
+enum mlx5_ib_devx_methods {
+	MLX5_IB_METHOD_DEVX_OTHER  = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum  mlx5_ib_devx_other_attrs {
+	MLX5_IB_ATTR_DEVX_OTHER_CMD_IN = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
+};
+
+enum mlx5_ib_devx_objects {
+	MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
+};
+
 #endif
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 15/20] IB/mlx5: Add obj create and destroy functionality
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (13 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH rdma-next v2 14/20] IB/mlx5: Add support for DEVX general command Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH mlx5-next v2 16/20] IB/mlx5: Add DEVX support for modify and query commands Leon Romanovsky
                   ` (5 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Add support to create and destroy firmware objects via the DEVX
interface.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c        | 332 ++++++++++++++++++++++++++++++-
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  16 ++
 2 files changed, 347 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 9fca6541a175..9939df0117d5 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -16,6 +16,14 @@
 #define UVERBS_MODULE_NAME mlx5_ib
 #include <rdma/uverbs_named_ioctl.h>
 
+#define MLX5_MAX_DESTROY_INBOX_SIZE_DW MLX5_ST_SZ_DW(delete_fte_in)
+struct devx_obj {
+	struct mlx5_core_dev	*mdev;
+	u32			obj_id;
+	u32			dinlen; /* destroy inbox length */
+	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
+};
+
 static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
 {
 	return to_mucontext(ib_uverbs_get_ucontext(file));
@@ -65,6 +73,51 @@ void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
 }
 
+static bool devx_is_obj_create_cmd(const void *in)
+{
+	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+
+	switch (opcode) {
+	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
+	case MLX5_CMD_OP_CREATE_MKEY:
+	case MLX5_CMD_OP_CREATE_CQ:
+	case MLX5_CMD_OP_ALLOC_PD:
+	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
+	case MLX5_CMD_OP_CREATE_RMP:
+	case MLX5_CMD_OP_CREATE_SQ:
+	case MLX5_CMD_OP_CREATE_RQ:
+	case MLX5_CMD_OP_CREATE_RQT:
+	case MLX5_CMD_OP_CREATE_TIR:
+	case MLX5_CMD_OP_CREATE_TIS:
+	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
+	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
+	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
+	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
+	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
+	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
+	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
+	case MLX5_CMD_OP_CREATE_QP:
+	case MLX5_CMD_OP_CREATE_SRQ:
+	case MLX5_CMD_OP_CREATE_XRC_SRQ:
+	case MLX5_CMD_OP_CREATE_DCT:
+	case MLX5_CMD_OP_CREATE_XRQ:
+	case MLX5_CMD_OP_ATTACH_TO_MCG:
+	case MLX5_CMD_OP_ALLOC_XRCD:
+		return true;
+	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
+	{
+		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
+		if (op_mod == 0)
+			return true;
+		return false;
+	}
+	default:
+		return false;
+	}
+}
+
 static bool devx_is_general_cmd(void *in)
 {
 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
@@ -126,6 +179,256 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(struct ib_device *ib_dev,
 	return err;
 }
 
+static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
+				       u32 *dinlen,
+				       u32 *obj_id)
+{
+	u16 obj_type = MLX5_GET(general_obj_in_cmd_hdr, in, obj_type);
+	u16 uid = MLX5_GET(general_obj_in_cmd_hdr, in, uid);
+
+	*obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
+	*dinlen = MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr);
+
+	MLX5_SET(general_obj_in_cmd_hdr, din, obj_id, *obj_id);
+	MLX5_SET(general_obj_in_cmd_hdr, din, uid, uid);
+
+	switch (MLX5_GET(general_obj_in_cmd_hdr, in, opcode)) {
+	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_GENERAL_OBJECT);
+		MLX5_SET(general_obj_in_cmd_hdr, din, obj_type, obj_type);
+		break;
+
+	case MLX5_CMD_OP_CREATE_MKEY:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_MKEY);
+		break;
+	case MLX5_CMD_OP_CREATE_CQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_CQ);
+		break;
+	case MLX5_CMD_OP_ALLOC_PD:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_PD);
+		break;
+	case MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN);
+		break;
+	case MLX5_CMD_OP_CREATE_RMP:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RMP);
+		break;
+	case MLX5_CMD_OP_CREATE_SQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SQ);
+		break;
+	case MLX5_CMD_OP_CREATE_RQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQ);
+		break;
+	case MLX5_CMD_OP_CREATE_RQT:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_RQT);
+		break;
+	case MLX5_CMD_OP_CREATE_TIR:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIR);
+		break;
+	case MLX5_CMD_OP_CREATE_TIS:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_TIS);
+		break;
+	case MLX5_CMD_OP_ALLOC_Q_COUNTER:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DEALLOC_Q_COUNTER);
+		break;
+	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
+		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_table_in);
+		*obj_id = MLX5_GET(create_flow_table_out, out, table_id);
+		MLX5_SET(destroy_flow_table_in, din, other_vport,
+			 MLX5_GET(create_flow_table_in,  in, other_vport));
+		MLX5_SET(destroy_flow_table_in, din, vport_number,
+			 MLX5_GET(create_flow_table_in,  in, vport_number));
+		MLX5_SET(destroy_flow_table_in, din, table_type,
+			 MLX5_GET(create_flow_table_in,  in, table_type));
+		MLX5_SET(destroy_flow_table_in, din, table_id, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
+		break;
+	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
+		*dinlen = MLX5_ST_SZ_BYTES(destroy_flow_group_in);
+		*obj_id = MLX5_GET(create_flow_group_out, out, group_id);
+		MLX5_SET(destroy_flow_group_in, din, other_vport,
+			 MLX5_GET(create_flow_group_in, in, other_vport));
+		MLX5_SET(destroy_flow_group_in, din, vport_number,
+			 MLX5_GET(create_flow_group_in, in, vport_number));
+		MLX5_SET(destroy_flow_group_in, din, table_type,
+			 MLX5_GET(create_flow_group_in, in, table_type));
+		MLX5_SET(destroy_flow_group_in, din, table_id,
+			 MLX5_GET(create_flow_group_in, in, table_id));
+		MLX5_SET(destroy_flow_group_in, din, group_id, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
+		break;
+	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
+		*dinlen = MLX5_ST_SZ_BYTES(delete_fte_in);
+		*obj_id = MLX5_GET(set_fte_in, in, flow_index);
+		MLX5_SET(delete_fte_in, din, other_vport,
+			 MLX5_GET(set_fte_in,  in, other_vport));
+		MLX5_SET(delete_fte_in, din, vport_number,
+			 MLX5_GET(set_fte_in, in, vport_number));
+		MLX5_SET(delete_fte_in, din, table_type,
+			 MLX5_GET(set_fte_in, in, table_type));
+		MLX5_SET(delete_fte_in, din, table_id,
+			 MLX5_GET(set_fte_in, in, table_id));
+		MLX5_SET(delete_fte_in, din, flow_index, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
+		break;
+	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
+		break;
+	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DEALLOC_ENCAP_HEADER);
+		break;
+	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT);
+		break;
+	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
+		*dinlen = MLX5_ST_SZ_BYTES(destroy_scheduling_element_in);
+		*obj_id = MLX5_GET(create_scheduling_element_out, out,
+				   scheduling_element_id);
+		MLX5_SET(destroy_scheduling_element_in, din,
+			 scheduling_hierarchy,
+			 MLX5_GET(create_scheduling_element_in, in,
+				  scheduling_hierarchy));
+		MLX5_SET(destroy_scheduling_element_in, din,
+			 scheduling_element_id, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DESTROY_SCHEDULING_ELEMENT);
+		break;
+	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
+		*dinlen = MLX5_ST_SZ_BYTES(delete_vxlan_udp_dport_in);
+		*obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
+		MLX5_SET(delete_vxlan_udp_dport_in, din, vxlan_udp_port, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DELETE_VXLAN_UDP_DPORT);
+		break;
+	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
+		*dinlen = MLX5_ST_SZ_BYTES(delete_l2_table_entry_in);
+		*obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
+		MLX5_SET(delete_l2_table_entry_in, din, table_index, *obj_id);
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY);
+		break;
+	case MLX5_CMD_OP_CREATE_QP:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_QP);
+		break;
+	case MLX5_CMD_OP_CREATE_SRQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_SRQ);
+		break;
+	case MLX5_CMD_OP_CREATE_XRC_SRQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
+			 MLX5_CMD_OP_DESTROY_XRC_SRQ);
+		break;
+	case MLX5_CMD_OP_CREATE_DCT:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
+		break;
+	case MLX5_CMD_OP_CREATE_XRQ:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DESTROY_XRQ);
+		break;
+	case MLX5_CMD_OP_ATTACH_TO_MCG:
+		*dinlen = MLX5_ST_SZ_BYTES(detach_from_mcg_in);
+		MLX5_SET(detach_from_mcg_in, din, qpn,
+			 MLX5_GET(attach_to_mcg_in, in, qpn));
+		memcpy(MLX5_ADDR_OF(detach_from_mcg_in, din, multicast_gid),
+		       MLX5_ADDR_OF(attach_to_mcg_in, in, multicast_gid),
+		       MLX5_FLD_SZ_BYTES(attach_to_mcg_in, multicast_gid));
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DETACH_FROM_MCG);
+		break;
+	case MLX5_CMD_OP_ALLOC_XRCD:
+		MLX5_SET(general_obj_in_cmd_hdr, din, opcode, MLX5_CMD_OP_DEALLOC_XRCD);
+		break;
+	default:
+		/* The entry must match to one of the devx_is_obj_create_cmd */
+		WARN_ON(true);
+		break;
+	}
+}
+
+static int devx_obj_cleanup(struct ib_uobject *uobject,
+			    enum rdma_remove_reason why)
+{
+	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
+	struct devx_obj *obj = uobject->object;
+	int ret;
+
+	ret = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
+	if (ret && why == RDMA_REMOVE_DESTROY)
+		return ret;
+
+	kfree(obj);
+	return ret;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_DESTROY)(struct ib_device *ib_dev,
+				    struct ib_uverbs_file *file,
+				    struct uverbs_attr_bundle *attrs)
+{
+	return 0;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(struct ib_device *ib_dev,
+				   struct ib_uverbs_file *file,
+				   struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN);
+	int cmd_out_len =  uverbs_attr_get_len(attrs,
+					MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT);
+	void *cmd_out;
+	struct ib_uobject *uobj;
+	struct devx_obj *obj;
+	int err;
+
+	if (!c->devx_uid)
+		return -EPERM;
+
+	if (!devx_is_obj_create_cmd(cmd_in))
+		return -EINVAL;
+
+	obj = kzalloc(sizeof(struct devx_obj), GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
+	if (!cmd_out) {
+		err = -ENOMEM;
+		goto obj_free;
+	}
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+	err = mlx5_cmd_exec(dev->mdev, cmd_in,
+			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN),
+			    cmd_out, cmd_out_len);
+	if (err)
+		goto cmd_free;
+
+	uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
+	uobj->object = obj;
+	obj->mdev = dev->mdev;
+	devx_obj_build_destroy_cmd(cmd_in, cmd_out, obj->dinbox, &obj->dinlen, &obj->obj_id);
+	WARN_ON(obj->dinlen > MLX5_MAX_DESTROY_INBOX_SIZE_DW * sizeof(u32));
+
+	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
+	if (err)
+		goto cmd_free;
+
+	kvfree(cmd_out);
+	return 0;
+
+cmd_free:
+	kvfree(cmd_out);
+obj_free:
+	kfree(obj);
+	return err;
+}
+
 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
 	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
 			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
@@ -138,8 +441,35 @@ static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
 					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO))
 );
 
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_OBJ,
+			 UVERBS_ACCESS_NEW,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
+			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
+			       UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
+					UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
+	&UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
+				UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
+				UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
+
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_OBJ,
+			 UVERBS_ACCESS_DESTROY,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
+
 static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER));
 
+static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
+	&UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
+		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
+		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY));
+
 static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
-	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX));
+	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
+	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ));
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index 0b456fa91bb4..8d285f4555cd 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -54,8 +54,24 @@ enum  mlx5_ib_devx_other_attrs {
 	MLX5_IB_ATTR_DEVX_OTHER_CMD_OUT,
 };
 
+enum mlx5_ib_devx_obj_create_attrs {
+	MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_IN,
+	MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
+};
+
+enum mlx5_ib_devx_obj_destroy_attrs {
+	MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum mlx5_ib_devx_obj_methods {
+	MLX5_IB_METHOD_DEVX_OBJ_CREATE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
+};
+
 enum mlx5_ib_devx_objects {
 	MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_OBJECT_DEVX_OBJ,
 };
 
 #endif
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH mlx5-next v2 16/20] IB/mlx5: Add DEVX support for modify and query commands
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (14 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH rdma-next v2 15/20] IB/mlx5: Add obj create and destroy functionality Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH rdma-next v2 17/20] IB/mlx5: Add support for DEVX query UAR Leon Romanovsky
                   ` (4 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Add support in DEVX for modify and query commands, the required lock is
taken (i.e. READ/WRITE) by the KABI infrastructure accordingly.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c             | 348 +++++++++++++++++++++++++-
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c |   5 +
 include/linux/mlx5/mlx5_ifc.h                 |   3 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h      |  14 ++
 4 files changed, 369 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 9939df0117d5..d1cf14874323 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -73,6 +73,161 @@ void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 	mlx5_cmd_exec(dev->mdev, in, sizeof(in), out, sizeof(out));
 }
 
+static int devx_is_valid_obj_id(struct devx_obj *obj, const void *in)
+{
+	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+	u32 obj_id;
+
+	switch (opcode) {
+	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
+	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
+		obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
+		break;
+	case MLX5_CMD_OP_QUERY_MKEY:
+		obj_id = MLX5_GET(query_mkey_in, in, mkey_index);
+		break;
+	case MLX5_CMD_OP_QUERY_CQ:
+		obj_id = MLX5_GET(query_cq_in, in, cqn);
+		break;
+	case MLX5_CMD_OP_MODIFY_CQ:
+		obj_id = MLX5_GET(modify_cq_in, in, cqn);
+		break;
+	case MLX5_CMD_OP_QUERY_SQ:
+		obj_id = MLX5_GET(query_sq_in, in, sqn);
+		break;
+	case MLX5_CMD_OP_MODIFY_SQ:
+		obj_id = MLX5_GET(modify_sq_in, in, sqn);
+		break;
+	case MLX5_CMD_OP_QUERY_RQ:
+		obj_id = MLX5_GET(query_rq_in, in, rqn);
+		break;
+	case MLX5_CMD_OP_MODIFY_RQ:
+		obj_id = MLX5_GET(modify_rq_in, in, rqn);
+		break;
+	case MLX5_CMD_OP_QUERY_RMP:
+		obj_id = MLX5_GET(query_rmp_in, in, rmpn);
+		break;
+	case MLX5_CMD_OP_MODIFY_RMP:
+		obj_id = MLX5_GET(modify_rmp_in, in, rmpn);
+		break;
+	case MLX5_CMD_OP_QUERY_RQT:
+		obj_id = MLX5_GET(query_rqt_in, in, rqtn);
+		break;
+	case MLX5_CMD_OP_MODIFY_RQT:
+		obj_id = MLX5_GET(modify_rqt_in, in, rqtn);
+		break;
+	case MLX5_CMD_OP_QUERY_TIR:
+		obj_id = MLX5_GET(query_tir_in, in, tirn);
+		break;
+	case MLX5_CMD_OP_MODIFY_TIR:
+		obj_id = MLX5_GET(modify_tir_in, in, tirn);
+		break;
+	case MLX5_CMD_OP_QUERY_TIS:
+		obj_id = MLX5_GET(query_tis_in, in, tisn);
+		break;
+	case MLX5_CMD_OP_MODIFY_TIS:
+		obj_id = MLX5_GET(modify_tis_in, in, tisn);
+		break;
+	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
+		obj_id = MLX5_GET(query_flow_table_in, in, table_id);
+		break;
+	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
+		obj_id = MLX5_GET(modify_flow_table_in, in, table_id);
+		break;
+	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
+		obj_id = MLX5_GET(query_flow_group_in, in, group_id);
+		break;
+	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
+		obj_id = MLX5_GET(query_fte_in, in, flow_index);
+		break;
+	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
+		obj_id = MLX5_GET(set_fte_in, in, flow_index);
+		break;
+	case MLX5_CMD_OP_QUERY_Q_COUNTER:
+		obj_id = MLX5_GET(query_q_counter_in, in, counter_set_id);
+		break;
+	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
+		obj_id = MLX5_GET(query_flow_counter_in, in, flow_counter_id);
+		break;
+	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
+		obj_id = MLX5_GET(general_obj_in_cmd_hdr, in, obj_id);
+		break;
+	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
+		obj_id = MLX5_GET(query_scheduling_element_in, in,
+				  scheduling_element_id);
+		break;
+	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
+		obj_id = MLX5_GET(modify_scheduling_element_in, in,
+				  scheduling_element_id);
+		break;
+	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
+		obj_id = MLX5_GET(add_vxlan_udp_dport_in, in, vxlan_udp_port);
+		break;
+	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
+		obj_id = MLX5_GET(query_l2_table_entry_in, in, table_index);
+		break;
+	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
+		obj_id = MLX5_GET(set_l2_table_entry_in, in, table_index);
+		break;
+	case MLX5_CMD_OP_QUERY_QP:
+		obj_id = MLX5_GET(query_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_RST2INIT_QP:
+		obj_id = MLX5_GET(rst2init_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_INIT2RTR_QP:
+		obj_id = MLX5_GET(init2rtr_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_RTR2RTS_QP:
+		obj_id = MLX5_GET(rtr2rts_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_RTS2RTS_QP:
+		obj_id = MLX5_GET(rts2rts_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_SQERR2RTS_QP:
+		obj_id = MLX5_GET(sqerr2rts_qp_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_2ERR_QP:
+		obj_id = MLX5_GET(qp_2err_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_2RST_QP:
+		obj_id = MLX5_GET(qp_2rst_in, in, qpn);
+		break;
+	case MLX5_CMD_OP_QUERY_DCT:
+		obj_id = MLX5_GET(query_dct_in, in, dctn);
+		break;
+	case MLX5_CMD_OP_QUERY_XRQ:
+		obj_id = MLX5_GET(query_xrq_in, in, xrqn);
+		break;
+	case MLX5_CMD_OP_QUERY_XRC_SRQ:
+		obj_id = MLX5_GET(query_xrc_srq_in, in, xrc_srqn);
+		break;
+	case MLX5_CMD_OP_ARM_XRC_SRQ:
+		obj_id = MLX5_GET(arm_xrc_srq_in, in, xrc_srqn);
+		break;
+	case MLX5_CMD_OP_QUERY_SRQ:
+		obj_id = MLX5_GET(query_srq_in, in, srqn);
+		break;
+	case MLX5_CMD_OP_ARM_RQ:
+		obj_id = MLX5_GET(arm_rq_in, in, srq_number);
+		break;
+	case MLX5_CMD_OP_DRAIN_DCT:
+	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
+		obj_id = MLX5_GET(drain_dct_in, in, dctn);
+		break;
+	case MLX5_CMD_OP_ARM_XRQ:
+		obj_id = MLX5_GET(arm_xrq_in, in, xrqn);
+		break;
+	default:
+		return false;
+	}
+
+	if (obj_id == obj->obj_id)
+		return true;
+
+	return false;
+}
+
 static bool devx_is_obj_create_cmd(const void *in)
 {
 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
@@ -118,6 +273,82 @@ static bool devx_is_obj_create_cmd(const void *in)
 	}
 }
 
+static bool devx_is_obj_modify_cmd(const void *in)
+{
+	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+
+	switch (opcode) {
+	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
+	case MLX5_CMD_OP_MODIFY_CQ:
+	case MLX5_CMD_OP_MODIFY_RMP:
+	case MLX5_CMD_OP_MODIFY_SQ:
+	case MLX5_CMD_OP_MODIFY_RQ:
+	case MLX5_CMD_OP_MODIFY_RQT:
+	case MLX5_CMD_OP_MODIFY_TIR:
+	case MLX5_CMD_OP_MODIFY_TIS:
+	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
+	case MLX5_CMD_OP_MODIFY_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
+	case MLX5_CMD_OP_SET_L2_TABLE_ENTRY:
+	case MLX5_CMD_OP_RST2INIT_QP:
+	case MLX5_CMD_OP_INIT2RTR_QP:
+	case MLX5_CMD_OP_RTR2RTS_QP:
+	case MLX5_CMD_OP_RTS2RTS_QP:
+	case MLX5_CMD_OP_SQERR2RTS_QP:
+	case MLX5_CMD_OP_2ERR_QP:
+	case MLX5_CMD_OP_2RST_QP:
+	case MLX5_CMD_OP_ARM_XRC_SRQ:
+	case MLX5_CMD_OP_ARM_RQ:
+	case MLX5_CMD_OP_DRAIN_DCT:
+	case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
+	case MLX5_CMD_OP_ARM_XRQ:
+		return true;
+	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
+	{
+		u16 op_mod = MLX5_GET(set_fte_in, in, op_mod);
+
+		if (op_mod == 1)
+			return true;
+		return false;
+	}
+	default:
+		return false;
+	}
+}
+
+static bool devx_is_obj_query_cmd(const void *in)
+{
+	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
+
+	switch (opcode) {
+	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
+	case MLX5_CMD_OP_QUERY_MKEY:
+	case MLX5_CMD_OP_QUERY_CQ:
+	case MLX5_CMD_OP_QUERY_RMP:
+	case MLX5_CMD_OP_QUERY_SQ:
+	case MLX5_CMD_OP_QUERY_RQ:
+	case MLX5_CMD_OP_QUERY_RQT:
+	case MLX5_CMD_OP_QUERY_TIR:
+	case MLX5_CMD_OP_QUERY_TIS:
+	case MLX5_CMD_OP_QUERY_Q_COUNTER:
+	case MLX5_CMD_OP_QUERY_FLOW_TABLE:
+	case MLX5_CMD_OP_QUERY_FLOW_GROUP:
+	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
+	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
+	case MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT:
+	case MLX5_CMD_OP_QUERY_SCHEDULING_ELEMENT:
+	case MLX5_CMD_OP_QUERY_L2_TABLE_ENTRY:
+	case MLX5_CMD_OP_QUERY_QP:
+	case MLX5_CMD_OP_QUERY_SRQ:
+	case MLX5_CMD_OP_QUERY_XRC_SRQ:
+	case MLX5_CMD_OP_QUERY_DCT:
+	case MLX5_CMD_OP_QUERY_XRQ:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static bool devx_is_general_cmd(void *in)
 {
 	u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, in, opcode);
@@ -429,6 +660,89 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(struct ib_device *ib_d
 	return err;
 }
 
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_MODIFY)(struct ib_device *ib_dev,
+				   struct ib_uverbs_file *file,
+				   struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN);
+	int cmd_out_len = uverbs_attr_get_len(attrs,
+					MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT);
+	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
+							  MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE);
+	void *cmd_out;
+	int err;
+
+	if (!c->devx_uid)
+		return -EPERM;
+
+	if (!devx_is_obj_modify_cmd(cmd_in))
+		return -EINVAL;
+
+	if (!devx_is_valid_obj_id(uobj->object, cmd_in))
+		return -EINVAL;
+
+	cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
+	if (!cmd_out)
+		return -ENOMEM;
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+	err = mlx5_cmd_exec(dev->mdev, cmd_in,
+			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN),
+			    cmd_out, cmd_out_len);
+	if (err)
+		goto other_cmd_free;
+
+	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
+			     cmd_out, cmd_out_len);
+
+other_cmd_free:
+	kvfree(cmd_out);
+	return err;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(struct ib_device *ib_dev,
+				   struct ib_uverbs_file *file,
+				   struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	void *cmd_in = uverbs_attr_get_alloced_ptr(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN);
+	int cmd_out_len = uverbs_attr_get_len(attrs,
+					      MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT);
+	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
+							  MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE);
+	void *cmd_out;
+	int err;
+
+	if (!c->devx_uid)
+		return -EPERM;
+
+	if (!devx_is_obj_query_cmd(cmd_in))
+		return -EINVAL;
+
+	if (!devx_is_valid_obj_id(uobj->object, cmd_in))
+		return -EINVAL;
+
+	cmd_out = kvzalloc(cmd_out_len, GFP_KERNEL);
+	if (!cmd_out)
+		return -ENOMEM;
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd_in, uid, c->devx_uid);
+	err = mlx5_cmd_exec(dev->mdev, cmd_in,
+			    uverbs_attr_get_len(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN),
+			    cmd_out, cmd_out_len);
+	if (err)
+		goto other_cmd_free;
+
+	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT, cmd_out, cmd_out_len);
+
+other_cmd_free:
+	kvfree(cmd_out);
+	return err;
+}
+
 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
 	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
 			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
@@ -462,13 +776,45 @@ static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
 			 UVERBS_ACCESS_DESTROY,
 			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_OBJ,
+			 UVERBS_ACCESS_WRITE,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
+			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
+			       UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
+					UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
+	&UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
+				UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
+				UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
+
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_OBJ,
+			 UVERBS_ACCESS_READ,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
+			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
+			       UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO |
+					UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY)),
+	&UVERBS_ATTR_PTR_OUT_SZ(MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
+				UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_out_cmd_hdr)),
+				UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY |
+					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
+
 static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER));
 
 static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
 	&UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
 		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_CREATE),
-		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY));
+		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_DESTROY),
+		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
+		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
 
 static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
 	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index d07f24de8fa3..9d03a202abb1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -429,6 +429,8 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_FPGA_QUERY_QP:
 	case MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS:
 	case MLX5_CMD_OP_CREATE_GENERAL_OBJECT:
+	case MLX5_CMD_OP_MODIFY_GENERAL_OBJECT:
+	case MLX5_CMD_OP_QUERY_GENERAL_OBJECT:
 		*status = MLX5_DRIVER_STATUS_ABORTED;
 		*synd = MLX5_DRIVER_SYND;
 		return -EIO;
@@ -603,6 +605,9 @@ const char *mlx5_command_str(int command)
 	MLX5_COMMAND_STR_CASE(FPGA_DESTROY_QP);
 	MLX5_COMMAND_STR_CASE(CREATE_GENERAL_OBJECT);
 	MLX5_COMMAND_STR_CASE(DESTROY_GENERAL_OBJECT);
+	MLX5_COMMAND_STR_CASE(MODIFY_GENERAL_OBJECT);
+	MLX5_COMMAND_STR_CASE(QUERY_GENERAL_OBJECT);
+	MLX5_COMMAND_STR_CASE(QUERY_MODIFY_HEADER_CONTEXT);
 	default: return "unknown command opcode";
 	}
 }
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index f810772e80c0..ac24ed87c67e 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -246,12 +246,15 @@ enum {
 	MLX5_CMD_OP_DEALLOC_ENCAP_HEADER          = 0x93e,
 	MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT   = 0x940,
 	MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT = 0x941,
+	MLX5_CMD_OP_QUERY_MODIFY_HEADER_CONTEXT   = 0x942,
 	MLX5_CMD_OP_FPGA_CREATE_QP                = 0x960,
 	MLX5_CMD_OP_FPGA_MODIFY_QP                = 0x961,
 	MLX5_CMD_OP_FPGA_QUERY_QP                 = 0x962,
 	MLX5_CMD_OP_FPGA_DESTROY_QP               = 0x963,
 	MLX5_CMD_OP_FPGA_QUERY_QP_COUNTERS        = 0x964,
 	MLX5_CMD_OP_CREATE_GENERAL_OBJECT         = 0xa00,
+	MLX5_CMD_OP_MODIFY_GENERAL_OBJECT         = 0xa01,
+	MLX5_CMD_OP_QUERY_GENERAL_OBJECT          = 0xa02,
 	MLX5_CMD_OP_DESTROY_GENERAL_OBJECT        = 0xa03,
 	MLX5_CMD_OP_MAX
 };
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index 8d285f4555cd..97d216b8d053 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -64,9 +64,23 @@ enum mlx5_ib_devx_obj_destroy_attrs {
 	MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
 };
 
+enum mlx5_ib_devx_obj_modify_attrs {
+	MLX5_IB_ATTR_DEVX_OBJ_MODIFY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_IN,
+	MLX5_IB_ATTR_DEVX_OBJ_MODIFY_CMD_OUT,
+};
+
+enum mlx5_ib_devx_obj_query_attrs {
+	MLX5_IB_ATTR_DEVX_OBJ_QUERY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_IN,
+	MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
+};
+
 enum mlx5_ib_devx_obj_methods {
 	MLX5_IB_METHOD_DEVX_OBJ_CREATE = (1U << UVERBS_ID_NS_SHIFT),
 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
+	MLX5_IB_METHOD_DEVX_OBJ_MODIFY,
+	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
 };
 
 enum mlx5_ib_devx_objects {
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 17/20] IB/mlx5: Add support for DEVX query UAR
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (15 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH mlx5-next v2 16/20] IB/mlx5: Add DEVX support for modify and query commands Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH mlx5-next v2 18/20] IB/mlx5: Add DEVX support for memory registration Leon Romanovsky
                   ` (3 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Return a device UAR index for a given user index via the DEVX interface.

Security note:
The hardware protection mechanism works like this: Each device object that
is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
the device specification manual) upon its creation. Then upon doorbell,
hardware fetches the object context for which the doorbell was rang, and
validates that the UAR through which the DB was rang matches the UAR ID
of the object.

If no match the doorbell is silently ignored by the hardware.  Of
course, the user cannot ring a doorbell on a UAR that was not mapped to
it.

Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
mailboxes (except tagging them with UID), we expose to the user its UAR
ID, so it can embed it in these objects in the expected specification
format. So the only thing the user can do is hurt itself by creating a
QP/SQ/CQ with a UAR ID other than his, and then in this case other users
may ring a doorbell on its objects.

The consequence of that will be that another user can schedule a QP/SQ
of the buggy user for execution (just insert it to the hardware schedule
queue or arm its CQ for event generation), no further harm is expected.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c        | 53 +++++++++++++++++++++++++++++++-
 drivers/infiniband/hw/mlx5/mlx5_ib.h     |  3 ++
 drivers/infiniband/hw/mlx5/qp.c          |  9 ++++--
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  6 ++++
 4 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index d1cf14874323..386142684637 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -373,6 +373,50 @@ static bool devx_is_general_cmd(void *in)
 	}
 }
 
+/*
+ *Security note:
+ * The hardware protection mechanism works like this: Each device object that
+ * is subject to UAR doorbells (QP/SQ/CQ) gets a UAR ID (called uar_page in
+ * the device specification manual) upon its creation. Then upon doorbell,
+ * hardware fetches the object context for which the doorbell was rang, and
+ * validates that the UAR through which the DB was rang matches the UAR ID
+ * of the object.
+ * If no match the doorbell is silently ignored by the hardware. Of course,
+ * the user cannot ring a doorbell on a UAR that was not mapped to it.
+ * Now in devx, as the devx kernel does not manipulate the QP/SQ/CQ command
+ * mailboxes (except tagging them with UID), we expose to the user its UAR
+ * ID, so it can embed it in these objects in the expected specification
+ * format. So the only thing the user can do is hurt itself by creating a
+ * QP/SQ/CQ with a UAR ID other than his, and then in this case other users
+ * may ring a doorbell on its objects.
+ * The consequence of that will be that another user can schedule a QP/SQ
+ * of the buggy user for execution (just insert it to the hardware schedule
+ * queue or arm its CQ for event generation), no further harm is expected.
+ */
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_UAR)(struct ib_device *ib_dev,
+				  struct ib_uverbs_file *file,
+				  struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	u32 user_idx;
+	s32 dev_idx;
+
+	if (uverbs_copy_from(&user_idx, attrs,
+			     MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX))
+		return -EFAULT;
+
+	dev_idx = bfregn_to_uar_index(to_mdev(ib_dev),
+				      &c->bfregi, user_idx, true);
+	if (dev_idx < 0)
+		return dev_idx;
+
+	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
+			   &dev_idx, sizeof(dev_idx)))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OTHER)(struct ib_device *ib_dev,
 				  struct ib_uverbs_file *file,
 				  struct uverbs_attr_bundle *attrs)
@@ -743,6 +787,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(struct ib_device *ib_de
 	return err;
 }
 
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
+	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
+			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX, UVERBS_ATTR_TYPE(u32),
+			     UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
+
 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OTHER,
 	&UVERBS_ATTR_PTR_IN_SZ(MLX5_IB_ATTR_DEVX_OTHER_CMD_IN,
 			       UVERBS_ATTR_MIN_SIZE(MLX5_ST_SZ_BYTES(general_obj_in_cmd_hdr)),
@@ -807,7 +857,8 @@ static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY,
 					 UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO)));
 
 static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
-	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER));
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR));
 
 static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
 	&UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 5e8abd8bcd71..a5560375047a 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1331,4 +1331,7 @@ static inline int get_num_static_uars(struct mlx5_ib_dev *dev,
 unsigned long mlx5_ib_get_xlt_emergency_page(void);
 void mlx5_ib_put_xlt_emergency_page(void);
 
+int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
+			struct mlx5_bfreg_info *bfregi, int bfregn,
+			bool dyn_bfreg);
 #endif /* MLX5_IB_H */
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index a4f1f638509f..f6389d0373d0 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -641,9 +641,9 @@ static void mlx5_ib_lock_cqs(struct mlx5_ib_cq *send_cq,
 static void mlx5_ib_unlock_cqs(struct mlx5_ib_cq *send_cq,
 			       struct mlx5_ib_cq *recv_cq);
 
-static int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
-			       struct mlx5_bfreg_info *bfregi, int bfregn,
-			       bool dyn_bfreg)
+int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
+			struct mlx5_bfreg_info *bfregi, int bfregn,
+			bool dyn_bfreg)
 {
 	int bfregs_per_sys_page;
 	int index_of_sys_page;
@@ -653,6 +653,9 @@ static int bfregn_to_uar_index(struct mlx5_ib_dev *dev,
 				MLX5_NON_FP_BFREGS_PER_UAR;
 	index_of_sys_page = bfregn / bfregs_per_sys_page;
 
+	if (index_of_sys_page >= bfregi->num_sys_pages)
+		return -EINVAL;
+
 	if (dyn_bfreg) {
 		index_of_sys_page += bfregi->num_static_sys_pages;
 		if (bfregn > bfregi->num_dyn_bfregs ||
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index 97d216b8d053..1252695cd94b 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -47,6 +47,7 @@ enum mlx5_ib_alloc_dm_attrs {
 
 enum mlx5_ib_devx_methods {
 	MLX5_IB_METHOD_DEVX_OTHER  = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_METHOD_DEVX_QUERY_UAR,
 };
 
 enum  mlx5_ib_devx_other_attrs {
@@ -60,6 +61,11 @@ enum mlx5_ib_devx_obj_create_attrs {
 	MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT,
 };
 
+enum  mlx5_ib_devx_query_uar_attrs {
+	MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_QUERY_UAR_DEV_IDX,
+};
+
 enum mlx5_ib_devx_obj_destroy_attrs {
 	MLX5_IB_ATTR_DEVX_OBJ_DESTROY_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
 };
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH mlx5-next v2 18/20] IB/mlx5: Add DEVX support for memory registration
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (16 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH rdma-next v2 17/20] IB/mlx5: Add support for DEVX query UAR Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH rdma-next v2 19/20] IB/mlx5: Add DEVX query EQN support Leon Romanovsky
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Add support to register a memory with the firmware via the DEVX
interface.

The driver translates a given user address to ib_umem then it will
register the physical addresses with the firmware and get a unique id
for this registration to be used for this virtual address.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c        | 199 ++++++++++++++++++++++++++++++-
 include/linux/mlx5/mlx5_ifc.h            |   1 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  18 +++
 3 files changed, 217 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index 386142684637..ba6b9b46cd90 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -24,6 +24,22 @@ struct devx_obj {
 	u32			dinbox[MLX5_MAX_DESTROY_INBOX_SIZE_DW];
 };
 
+struct devx_umem {
+	struct mlx5_core_dev		*mdev;
+	struct ib_umem			*umem;
+	u32				page_offset;
+	int				page_shift;
+	int				ncont;
+	u32				dinlen;
+	u32				dinbox[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)];
+};
+
+struct devx_umem_reg_cmd {
+	void				*in;
+	u32				inlen;
+	u32				out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
+};
+
 static struct mlx5_ib_ucontext *devx_ufile2uctx(struct ib_uverbs_file *file)
 {
 	return to_mucontext(ib_uverbs_get_ucontext(file));
@@ -787,6 +803,181 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(struct ib_device *ib_de
 	return err;
 }
 
+static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
+			 struct uverbs_attr_bundle *attrs,
+			 struct devx_umem *obj)
+{
+	u64 addr;
+	size_t size;
+	int access;
+	int npages;
+	int err;
+	u32 page_mask;
+
+	if (uverbs_copy_from(&addr, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR) ||
+	    uverbs_copy_from(&size, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_LEN) ||
+	    uverbs_copy_from(&access, attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS))
+		return -EFAULT;
+
+	err = ib_check_mr_access(access);
+	if (err)
+		return err;
+
+	obj->umem = ib_umem_get(ucontext, addr, size, access, 0);
+	if (IS_ERR(obj->umem))
+		return PTR_ERR(obj->umem);
+
+	mlx5_ib_cont_pages(obj->umem, obj->umem->address,
+			   MLX5_MKEY_PAGE_SHIFT_MASK, &npages,
+			   &obj->page_shift, &obj->ncont, NULL);
+
+	if (!npages) {
+		ib_umem_release(obj->umem);
+		return -EINVAL;
+	}
+
+	page_mask = (1 << obj->page_shift) - 1;
+	obj->page_offset = obj->umem->address & page_mask;
+
+	return 0;
+}
+
+static int devx_umem_reg_cmd_alloc(struct devx_umem *obj,
+				   struct devx_umem_reg_cmd *cmd)
+{
+	cmd->inlen = MLX5_ST_SZ_BYTES(create_umem_in) +
+		    (MLX5_ST_SZ_BYTES(mtt) * obj->ncont);
+	cmd->in = kvzalloc(cmd->inlen, GFP_KERNEL);
+	return cmd->in ? 0 : -ENOMEM;
+}
+
+static void devx_umem_reg_cmd_free(struct devx_umem_reg_cmd *cmd)
+{
+	kvfree(cmd->in);
+}
+
+static void devx_umem_reg_cmd_build(struct mlx5_ib_dev *dev,
+				    struct devx_umem *obj,
+				    struct devx_umem_reg_cmd *cmd)
+{
+	void *umem;
+	__be64 *mtt;
+
+	umem = MLX5_ADDR_OF(create_umem_in, cmd->in, umem);
+	mtt = (__be64 *)MLX5_ADDR_OF(umem, umem, mtt);
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd->in, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
+	MLX5_SET(general_obj_in_cmd_hdr, cmd->in, obj_type, MLX5_OBJ_TYPE_UMEM);
+	MLX5_SET64(umem, umem, num_of_mtt, obj->ncont);
+	MLX5_SET(umem, umem, log_page_size, obj->page_shift -
+					    MLX5_ADAPTER_PAGE_SHIFT);
+	MLX5_SET(umem, umem, page_offset, obj->page_offset);
+	mlx5_ib_populate_pas(dev, obj->umem, obj->page_shift, mtt,
+			     (obj->umem->writable ? MLX5_IB_MTT_WRITE : 0) |
+			     MLX5_IB_MTT_READ);
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_REG)(struct ib_device *ib_dev,
+				 struct ib_uverbs_file *file,
+				 struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_ucontext *c = devx_ufile2uctx(file);
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	struct devx_umem_reg_cmd cmd;
+	struct devx_umem *obj;
+	struct ib_uobject *uobj;
+	u32 obj_id;
+	int err;
+
+	if (!c->devx_uid)
+		return -EPERM;
+
+	uobj = uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE);
+	obj = kzalloc(sizeof(struct devx_umem), GFP_KERNEL);
+	if (!obj)
+		return -ENOMEM;
+
+	err = devx_umem_get(dev, &c->ibucontext, attrs, obj);
+	if (err)
+		goto err_obj_free;
+
+	err = devx_umem_reg_cmd_alloc(obj, &cmd);
+	if (err)
+		goto err_umem_release;
+
+	devx_umem_reg_cmd_build(dev, obj, &cmd);
+
+	MLX5_SET(general_obj_in_cmd_hdr, cmd.in, uid, c->devx_uid);
+	err = mlx5_cmd_exec(dev->mdev, cmd.in, cmd.inlen, cmd.out,
+			    sizeof(cmd.out));
+	if (err)
+		goto err_umem_reg_cmd_free;
+
+	obj->mdev = dev->mdev;
+	uobj->object = obj;
+	devx_obj_build_destroy_cmd(cmd.in, cmd.out, obj->dinbox, &obj->dinlen, &obj_id);
+	err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, &obj_id, sizeof(obj_id));
+	if (err)
+		goto err_umem_destroy;
+
+	devx_umem_reg_cmd_free(&cmd);
+
+	return 0;
+
+err_umem_destroy:
+	mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, cmd.out, sizeof(cmd.out));
+err_umem_reg_cmd_free:
+	devx_umem_reg_cmd_free(&cmd);
+err_umem_release:
+	ib_umem_release(obj->umem);
+err_obj_free:
+	kfree(obj);
+	return err;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_UMEM_DEREG)(struct ib_device *ib_dev,
+				   struct ib_uverbs_file *file,
+				   struct uverbs_attr_bundle *attrs)
+{
+	return 0;
+}
+
+static int devx_umem_cleanup(struct ib_uobject *uobject,
+			     enum rdma_remove_reason why)
+{
+	struct devx_umem *obj = uobject->object;
+	u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
+	int err;
+
+	err = mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
+	if (err && why == RDMA_REMOVE_DESTROY)
+		return err;
+
+	ib_umem_release(obj->umem);
+	kfree(obj);
+	return 0;
+}
+
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_UMEM,
+			 UVERBS_ACCESS_NEW,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR, UVERBS_ATTR_TYPE(u64),
+			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_LEN, UVERBS_ATTR_TYPE(u64),
+			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS, UVERBS_ATTR_TYPE(u32),
+			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID, UVERBS_ATTR_TYPE(u32),
+			     UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
+
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG,
+	&UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE,
+			 MLX5_IB_OBJECT_DEVX_UMEM,
+			 UVERBS_ACCESS_DESTROY,
+			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
+
 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
 	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
 			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
@@ -867,6 +1058,12 @@ static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
 		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_MODIFY),
 		&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY));
 
+static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
+	&UVERBS_TYPE_ALLOC_IDR(devx_umem_cleanup),
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
+
 static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
 	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
-	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ));
+	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
+	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index ac24ed87c67e..00b539303f5d 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -82,6 +82,7 @@ enum {
 
 enum {
 	MLX5_OBJ_TYPE_UCTX = 0x0004,
+	MLX5_OBJ_TYPE_UMEM = 0x0005,
 };
 
 enum {
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index 1252695cd94b..dbc549a7bf50 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -89,9 +89,27 @@ enum mlx5_ib_devx_obj_methods {
 	MLX5_IB_METHOD_DEVX_OBJ_QUERY,
 };
 
+enum mlx5_ib_devx_umem_reg_attrs {
+	MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_UMEM_REG_ADDR,
+	MLX5_IB_ATTR_DEVX_UMEM_REG_LEN,
+	MLX5_IB_ATTR_DEVX_UMEM_REG_ACCESS,
+	MLX5_IB_ATTR_DEVX_UMEM_REG_OUT_ID,
+};
+
+enum mlx5_ib_devx_umem_dereg_attrs {
+	MLX5_IB_ATTR_DEVX_UMEM_DEREG_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum mlx5_ib_devx_umem_methods {
+	MLX5_IB_METHOD_DEVX_UMEM_REG = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_METHOD_DEVX_UMEM_DEREG,
+};
+
 enum mlx5_ib_devx_objects {
 	MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
 	MLX5_IB_OBJECT_DEVX_OBJ,
+	MLX5_IB_OBJECT_DEVX_UMEM,
 };
 
 #endif
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 19/20] IB/mlx5: Add DEVX query EQN support
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (17 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH mlx5-next v2 18/20] IB/mlx5: Add DEVX support for memory registration Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-17 10:00 ` [PATCH rdma-next v2 20/20] IB/mlx5: Expose DEVX tree Leon Romanovsky
  2018-06-18 22:05 ` [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Jason Gunthorpe
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Return the matching device EQN for a given user vector number via the
DEVX interface.

Note:
EQs are owned by the kernel and shared by all user processes.
Basically, a user CQ can point to any EQ.
The kernel doesn't enforce any such limitation today either.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c        | 34 +++++++++++++++++++++++++++++++-
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  6 ++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index ba6b9b46cd90..de1a418331b2 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -389,6 +389,31 @@ static bool devx_is_general_cmd(void *in)
 	}
 }
 
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(struct ib_device *ib_dev,
+				  struct ib_uverbs_file *file,
+				  struct uverbs_attr_bundle *attrs)
+{
+	struct mlx5_ib_dev *dev = to_mdev(ib_dev);
+	int user_vector;
+	int dev_eqn;
+	unsigned int irqn;
+	int err;
+
+	if (uverbs_copy_from(&user_vector, attrs,
+			     MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC))
+		return -EFAULT;
+
+	err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
+	if (err < 0)
+		return err;
+
+	if (uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
+			   &dev_eqn, sizeof(dev_eqn)))
+		return -EFAULT;
+
+	return 0;
+}
+
 /*
  *Security note:
  * The hardware protection mechanism works like this: Each device object that
@@ -978,6 +1003,12 @@ static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG,
 			 UVERBS_ACCESS_DESTROY,
 			 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
+static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN,
+	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC, UVERBS_ATTR_TYPE(u32),
+			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
+	&UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN, UVERBS_ATTR_TYPE(u32),
+			     UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
+
 static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR,
 	&UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_DEVX_QUERY_UAR_USER_IDX, UVERBS_ATTR_TYPE(u32),
 			    UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
@@ -1049,7 +1080,8 @@ static DECLARE_UVERBS_NAMED_METHOD(MLX5_IB_METHOD_DEVX_OBJ_QUERY,
 
 static DECLARE_UVERBS_GLOBAL_METHODS(MLX5_IB_OBJECT_DEVX,
 	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_OTHER),
-	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR));
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_UAR),
+	&UVERBS_METHOD(MLX5_IB_METHOD_DEVX_QUERY_EQN));
 
 static DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ,
 	&UVERBS_TYPE_ALLOC_IDR(devx_obj_cleanup),
diff --git a/include/uapi/rdma/mlx5_user_ioctl_cmds.h b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
index dbc549a7bf50..1a05bb4b0b34 100644
--- a/include/uapi/rdma/mlx5_user_ioctl_cmds.h
+++ b/include/uapi/rdma/mlx5_user_ioctl_cmds.h
@@ -48,6 +48,7 @@ enum mlx5_ib_alloc_dm_attrs {
 enum mlx5_ib_devx_methods {
 	MLX5_IB_METHOD_DEVX_OTHER  = (1U << UVERBS_ID_NS_SHIFT),
 	MLX5_IB_METHOD_DEVX_QUERY_UAR,
+	MLX5_IB_METHOD_DEVX_QUERY_EQN,
 };
 
 enum  mlx5_ib_devx_other_attrs {
@@ -82,6 +83,11 @@ enum mlx5_ib_devx_obj_query_attrs {
 	MLX5_IB_ATTR_DEVX_OBJ_QUERY_CMD_OUT,
 };
 
+enum  mlx5_ib_devx_query_eqn_attrs {
+	MLX5_IB_ATTR_DEVX_QUERY_EQN_USER_VEC = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_DEVX_QUERY_EQN_DEV_EQN,
+};
+
 enum mlx5_ib_devx_obj_methods {
 	MLX5_IB_METHOD_DEVX_OBJ_CREATE = (1U << UVERBS_ID_NS_SHIFT),
 	MLX5_IB_METHOD_DEVX_OBJ_DESTROY,
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH rdma-next v2 20/20] IB/mlx5: Expose DEVX tree
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (18 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH rdma-next v2 19/20] IB/mlx5: Add DEVX query EQN support Leon Romanovsky
@ 2018-06-17 10:00 ` Leon Romanovsky
  2018-06-18 22:05 ` [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Jason Gunthorpe
  20 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-17 10:00 UTC (permalink / raw)
  To: Doug Ledford, Jason Gunthorpe
  Cc: Leon Romanovsky, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

From: Yishai Hadas <yishaih@mellanox.com>

Expose DEVX tree to be used by upper layers.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/hw/mlx5/devx.c    | 5 +++++
 drivers/infiniband/hw/mlx5/main.c    | 7 ++++++-
 drivers/infiniband/hw/mlx5/mlx5_ib.h | 3 +++
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index de1a418331b2..875f8c705ab9 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -1099,3 +1099,8 @@ static DECLARE_UVERBS_OBJECT_TREE(devx_objects,
 	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX),
 	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_OBJ),
 	&UVERBS_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM));
+
+const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void)
+{
+	return &devx_objects;
+}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 430a9e36d392..c7c31bbbca72 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -5290,7 +5290,7 @@ ADD_UVERBS_ATTRIBUTES_SIMPLE(mlx5_ib_flow_action, UVERBS_OBJECT_FLOW_ACTION,
 						 UVERBS_ATTR_TYPE(u64),
 						 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
 
-#define NUM_TREES	2
+#define NUM_TREES	3
 static int populate_specs_root(struct mlx5_ib_dev *dev)
 {
 	const struct uverbs_object_tree_def *default_root[NUM_TREES + 1] = {
@@ -5305,6 +5305,11 @@ static int populate_specs_root(struct mlx5_ib_dev *dev)
 	    !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
 		default_root[num_trees++] = &mlx5_ib_dm;
 
+	if (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &
+			    MLX5_GENERAL_OBJ_TYPES_CAP_UCTX &&
+	    !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
+		default_root[num_trees++] = mlx5_ib_get_devx_tree();
+
 	dev->ib_dev.specs_root =
 		uverbs_alloc_spec_tree(num_trees, default_root);
 
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index a5560375047a..be8615de14fc 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -1223,12 +1223,15 @@ int mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
 			struct mlx5_ib_ucontext *context);
 void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 			  struct mlx5_ib_ucontext *context);
+const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void);
 #else
 static inline int
 mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
 		    struct mlx5_ib_ucontext *context) { return -EOPNOTSUPP; };
 static inline void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 					struct mlx5_ib_ucontext *context) {}
+static inline const struct uverbs_object_tree_def *
+mlx5_ib_get_devx_tree(void) { return NULL; }
 #endif
 static inline void init_query_mad(struct ib_smp *mad)
 {
-- 
2.14.4

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm
  2018-06-17  9:59 ` [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm Leon Romanovsky
@ 2018-06-17 19:51   ` Jason Gunthorpe
  2018-06-18 11:27     ` Yishai Hadas
  0 siblings, 1 reply; 27+ messages in thread
From: Jason Gunthorpe @ 2018-06-17 19:51 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, Leon Romanovsky, RDMA mailing list,
	Joonas Lahtinen, Matan Barak, Yishai Hadas, Saeed Mahameed,
	linux-netdev

On Sun, Jun 17, 2018 at 12:59:55PM +0300, Leon Romanovsky wrote:

> +void uverbs_cleanup_ucontext(struct ib_ucontext *ucontext, bool device_removed)
> +{
>  	/*
>  	 * Waits for all remove_commit and alloc_commit to finish. Logically, We
>  	 * want to hold this forever as the context is going to be destroyed,
>  	 * but we'll release it since it causes a "held lock freed" BUG message.
>  	 */
>  	down_write(&ucontext->cleanup_rwsem);
> +	while (!list_empty(&ucontext->uobjects))
> +		if (__uverbs_cleanup_ucontext(ucontext, RDMA_REMOVE_DESTROY))
> +			/* No entry was cleaned-up successfully during this iteration */
> +			break;

No, this isn't right, it must remain REMOVE or CLOSE here. The enum is
a signal to the driver what is going on. DESTROY is only for user
triggered destroy called in a user context.

There needs to be some kind of guarenteed return from the driver that
destroy is failing due to elevated refcounts, and not some other
reason.. This is just checking for any ret?

> -	while (!list_empty(&ucontext->uobjects)) {
> -		struct ib_uobject *obj, *next_obj;
> -		unsigned int next_order = UINT_MAX;
> +	if (!list_empty(&ucontext->uobjects))
> +		__uverbs_cleanup_ucontext(ucontext, device_removed ?
> +			RDMA_REMOVE_DRIVER_REMOVE : RDMA_REMOVE_CLOSE);

Failure to cleanup is a driver bug, and should be reported with
WARN_ON. This is also mis using the remove enum, CLOSE is not a
'bigger hammer'

Jason

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm
  2018-06-17 19:51   ` Jason Gunthorpe
@ 2018-06-18 11:27     ` Yishai Hadas
  0 siblings, 0 replies; 27+ messages in thread
From: Yishai Hadas @ 2018-06-18 11:27 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Leon Romanovsky, Doug Ledford, Leon Romanovsky,
	RDMA mailing list, Joonas Lahtinen, Matan Barak, Yishai Hadas,
	Saeed Mahameed, linux-netdev, Majd Dibbiny

On 6/17/2018 10:51 PM, Jason Gunthorpe wrote:
> On Sun, Jun 17, 2018 at 12:59:55PM +0300, Leon Romanovsky wrote:
> 
>> +void uverbs_cleanup_ucontext(struct ib_ucontext *ucontext, bool device_removed)
>> +{
>>   	/*
>>   	 * Waits for all remove_commit and alloc_commit to finish. Logically, We
>>   	 * want to hold this forever as the context is going to be destroyed,
>>   	 * but we'll release it since it causes a "held lock freed" BUG message.
>>   	 */
>>   	down_write(&ucontext->cleanup_rwsem);
>> +	while (!list_empty(&ucontext->uobjects))
>> +		if (__uverbs_cleanup_ucontext(ucontext, RDMA_REMOVE_DESTROY))
>> +			/* No entry was cleaned-up successfully during this iteration */
>> +			break;
> 
> No, this isn't right, it must remain REMOVE or CLOSE here. The enum is
> a signal to the driver what is going on. DESTROY is only for user
> triggered destroy called in a user context.
> 

The algorithm must enable the drivers an option to fully cleanup their 
resources as was done before this change.

Using REMOVE or CLOSE without some following change won't do the work as 
the infrastructure (e.g. remove_commit_idr_uobject) and other IB cleanup 
functions during the road (e.g. uverbs_free_qp, uverbs_free_cq) will 
force cleanup of some memory/idr/ref resources and prevent a second 
successful iteration in case of a failure.

For that reason the initial iteration should be with some relaxed mode 
and just later in case were left uncleaned-up resources the code should 
use the REMOVE/CLOSE option.

However, I do agree that we need to preserve the original signal to let 
downstream layers to know what happened, at the moment it looks like 
there is one place that it's even a must as part of 
uverbs_hot_unplug_completion_event_file() where 
'RDMA_REMOVE_DRIVER_REMOVE' is used explicitly as part of the cleanup flow.

For that I suggest below [1] patch which replaces RDMA_REMOVE_DESTROY in 
the first iteration with RDMA_REMOVE_DRIVER_REMOVE_RELAX/ 
RDMA_REMOVE_CLOSE_RELAX new enum values to do the job.

> There needs to be some kind of guarenteed return from the driver that
> destroy is failing due to elevated refcounts, and not some other
> reason.. This is just checking for any ret?

We can't rely on all drivers' return codes from legacy/current firmware 
code for all objects to return a specific ret code for that case.
Even if we had such, the second iteration where we should force cleanup 
might still fail with that ret code and a kernel memory leak would occur.

> 
>> -	while (!list_empty(&ucontext->uobjects)) {
>> -		struct ib_uobject *obj, *next_obj;
>> -		unsigned int next_order = UINT_MAX;
>> +	if (!list_empty(&ucontext->uobjects))
>> +		__uverbs_cleanup_ucontext(ucontext, device_removed ?
>> +			RDMA_REMOVE_DRIVER_REMOVE : RDMA_REMOVE_CLOSE);
> 
> Failure to cleanup is a driver bug, and should be reported with
> WARN_ON. This is also mis using the remove enum, CLOSE is not a
> 'bigger hammer'
> 

The patch saves the previous behavior that set a warn message [2] and 
not a WARN_ON, if you think that WARN_ON is better we can change to.

[2]
pr_warn("ib_uverbs: unable to remove uobject id %d err %d\n",
				obj->id, err);


The suggested patch on top of current can look like below.


diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 4685ef5..6b03ca7
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1468,8 +1468,21 @@ enum rdma_remove_reason {
         RDMA_REMOVE_DRIVER_REMOVE,
         /* Context is being cleaned-up, but commit was just completed */
         RDMA_REMOVE_DURING_CLEANUP,
+       /* Driver is being hot-unplugged, retry may be called upon an 
error */
+       RDMA_REMOVE_DRIVER_REMOVE_RELAX,
+       /* Context deletion, retry may be called upon an error */
+       RDMA_REMOVE_CLOSE_RELAX,
  };

+static inline bool ib_is_remove_retry(enum rdma_remove_reason why)
+{
+       if (why == RDMA_REMOVE_DESTROY || why == 
RDMA_REMOVE_DRIVER_REMOVE_RELAX ||
+               why == RDMA_REMOVE_CLOSE_RELAX)
+               return true;
+
+       return false;
+}
+


// In the new algorithm below enums will be used instead of 
//RDMA_REMOVE_DESTROY

@@ -700,7 +701,9 @@ void uverbs_cleanup_ucontext(struct ib_ucontext 
*ucontext, bool device_removed)
          */
         down_write(&ucontext->cleanup_rwsem);
         while (!list_empty(&ucontext->uobjects))
-               if (__uverbs_cleanup_ucontext(ucontext, 
RDMA_REMOVE_DESTROY))
+               if (__uverbs_cleanup_ucontext(ucontext, device_removed ?
+                                       RDMA_REMOVE_DRIVER_REMOVE_RELAX :
+                                       RDMA_REMOVE_CLOSE_RELAX))
                         /* No entry was cleaned-up successfully during 
this iteration */
                         break;


// Below logic will be replaced in all applicable places, I just put few 
// of to demonstrate the solution.

--- a/drivers/infiniband/core/uverbs_std_types_cq.c
+++ b/drivers/infiniband/core/uverbs_std_types_cq.c
@@ -44,7 +44,7 @@ static int uverbs_free_cq(struct ib_uobject *uobject,
         int ret;

         ret = ib_destroy_cq(cq);
-       if (!ret || why != RDMA_REMOVE_DESTROY)
+       if (!ret || !ib_is_remove_retry(why))
                 ib_uverbs_release_ucq(uobject->context->ufile, ev_queue 
? container_of(ev_queue, struct ib_uverbs_completion_event_file,


++ b/drivers/infiniband/core/rdma_core.c
@@ -360,9 +360,10 @@ static int __must_check 
remove_commit_idr_uobject(struct ib_uobject *uobj,

         /*
          * We can only fail gracefully if the user requested to destroy the
-        * object. In the rest of the cases, just remove whatever you can.
+        * object or when a retry may be called upon an error.
+        * In the rest of the cases, just remove whatever you can.
          */
-       if (why == RDMA_REMOVE_DESTROY && ret)
+       if (ret && ib_is_remove_retry(why))
                 return ret;

         ib_rdmacg_uncharge(&uobj->cg_obj, uobj->context->device,
@@ -393,7 +394,7 @@ static int __must_check 
remove_commit_fd_uobject(struct ib_uobject *uobj,
                 container_of(uobj, struct ib_uobject_file, uobj);
         int ret = fd_type->context_closed(uobj_file, why);

-       if (why == RDMA_REMOVE_DESTROY && ret)
+       if (ret && ib_is_remove_retry(why))
                 return ret;


//Here is the specific place that checks for RDMA_REMOVE_DRIVER_REMOVE. 
// it should do the work also when RDMA_REMOVE_DRIVER_REMOVE was called.

@@ -187,7 +187,7 @@ static int 
uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_
         event_queue->is_closed = 1;
         spin_unlock_irq(&event_queue->lock);

-       if (why == RDMA_REMOVE_DRIVER_REMOVE) {
+       if (why == RDMA_REMOVE_DRIVER_REMOVE || why == 
RDMA_REMOVE_DRIVER_REMOVE_RELAX) {
                 wake_up_interruptible(&event_queue->poll_wait);
                 kill_fasync(&event_queue->async_queue, SIGIO, POLL_IN);
         }


What do you think ?

Yishai

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically
  2018-06-17  9:59 ` [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically Leon Romanovsky
@ 2018-06-18 20:48   ` Jason Gunthorpe
  0 siblings, 0 replies; 27+ messages in thread
From: Jason Gunthorpe @ 2018-06-18 20:48 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, Leon Romanovsky, RDMA mailing list,
	Joonas Lahtinen, Yishai Hadas, Saeed Mahameed, linux-netdev

On Sun, Jun 17, 2018 at 12:59:52PM +0300, Leon Romanovsky wrote:
> From: Matan Barak <matanb@mellanox.com>
> 
> Adding UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY flag to PTR_IN attributes.
> By using this flag, the parse automatically allocates and copies the
> user-space data. This data is accessible by using uverbs_attr_get_len
> and uverbs_attr_get_alloced_ptr inline accessor functions from the
> handler.
> 
> Signed-off-by: Matan Barak <matanb@mellanox.com>
> Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
> Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
>  drivers/infiniband/core/uverbs_ioctl.c | 25 ++++++++++++++++++++++++-
>  include/rdma/uverbs_ioctl.h            | 25 +++++++++++++++++++++++++
>  2 files changed, 49 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
> index 8cc3e8dad9b5..ee15c9ca788b 100644
> +++ b/drivers/infiniband/core/uverbs_ioctl.c
> @@ -114,7 +114,26 @@ static int uverbs_process_attr(struct ib_device *ibdev,
>  		    uattr->attr_data.reserved)
>  			return -EINVAL;
>  
> -		e->ptr_attr.data = uattr->data;
> +		if (val_spec->flags & UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY &&
> +		    uattr->len > sizeof(((struct ib_uverbs_attr *)0)->data)) {

Why open-code uverbs_attr_ptr_is_inline() ?

> diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
> index bd6bba3a6e04..0e6f782727bd 100644
> +++ b/include/rdma/uverbs_ioctl.h
> @@ -65,6 +65,8 @@ enum {
>  	UVERBS_ATTR_SPEC_F_MANDATORY	= 1U << 0,
>  	/* Support extending attributes by length, validate all unknown size == zero  */
>  	UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
> +	/* Valid only for PTR_IN. Allocate and copy the data inside the parser */
> +	UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY = 1U << 2,
>  };
>  
>  /* Specification of a single attribute inside the ioctl message */
> @@ -431,6 +433,17 @@ static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_att
>  	return attr->obj_attr.uobject;
>  }
>  
> +static inline int uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle,
> +				      u16 idx)
> +{
> +	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
> +
> +	if (IS_ERR(attr))
> +		return PTR_ERR(attr);
> +
> +	return attr->ptr_attr.len;
> +}
> +
>  static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
>  				 size_t idx, const void *from, size_t size)
>  {
> @@ -457,6 +470,18 @@ static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
>  	return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
>  }
>  
> +static inline void *uverbs_attr_get_alloced_ptr(const struct uverbs_attr_bundle *attrs_bundle,
> +						u16 idx)
> +{
> +	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
> +
> +	if (IS_ERR(attr))
> +		return (void *)attr;
> +
> +	return uverbs_attr_ptr_is_inline(attr) ? u64_to_ptr(void *, attr->ptr_attr.data) :
> +		u64_to_ptr(void, attr->ptr_attr.data);

WTF is this:

   u64_to_ptr(void *, attr->ptr_attr.data) 

That returns attr->ptr_attr.data casted to a void **, then casts it to
a void * - which is identical to u64_to_ptr(void, attr->ptr_attr.data)

It should be &attr->ptr_attr.data. And the return should be const, the
caller shouldn't be mutating the copy.

All this use of u64_to_ptr is ugly needless obfuscation here, and
look, it causes bugs. Use a union.

Like this:

diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c
index 8cc3e8dad9b506..82c5d33195dfc7 100644
--- a/drivers/infiniband/core/uverbs_ioctl.c
+++ b/drivers/infiniband/core/uverbs_ioctl.c
@@ -114,9 +114,27 @@ static int uverbs_process_attr(struct ib_device *ibdev,
 		    uattr->attr_data.reserved)
 			return -EINVAL;
 
-		e->ptr_attr.data = uattr->data;
 		e->ptr_attr.len = uattr->len;
 		e->ptr_attr.flags = uattr->flags;
+
+		if (val_spec->flags & UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY &&
+		    !uverbs_attr_ptr_is_inline(e)) {
+			void *p;
+
+			p = kvmalloc(uattr->len, GFP_KERNEL);
+			if (!p)
+				return -ENOMEM;
+
+			e->ptr_attr.ptr = p;
+
+			if (copy_from_user(p, u64_to_user_ptr(uattr->data),
+					   uattr->len)) {
+				kvfree(p);
+				return -EFAULT;
+			}
+		} else {
+			e->ptr_attr.data = uattr->data;
+		}
 		break;
 
 	case UVERBS_ATTR_TYPE_IDR:
@@ -201,6 +219,10 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 								     commit);
 				if (!ret)
 					ret = current_ret;
+			} else if (spec->type == UVERBS_ATTR_TYPE_PTR_IN &&
+				   spec->flags & UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY &&
+				   !uverbs_attr_ptr_is_inline(attr)) {
+				kvfree(attr->ptr_attr.ptr);
 			}
 		}
 	}
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h
index bd6bba3a6e04a1..6e1c322ff5c015 100644
--- a/include/rdma/uverbs_ioctl.h
+++ b/include/rdma/uverbs_ioctl.h
@@ -65,6 +65,8 @@ enum {
 	UVERBS_ATTR_SPEC_F_MANDATORY	= 1U << 0,
 	/* Support extending attributes by length, validate all unknown size == zero  */
 	UVERBS_ATTR_SPEC_F_MIN_SZ_OR_ZERO = 1U << 1,
+	/* Valid only for PTR_IN. Allocate and copy the data inside the parser */
+	UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY = 1U << 2,
 };
 
 /* Specification of a single attribute inside the ioctl message */
@@ -323,7 +325,15 @@ struct uverbs_object_tree_def {
  */
 
 struct uverbs_ptr_attr {
-	u64		data;
+	/*
+	 * If UVERBS_ATTR_SPEC_F_ALLOC_AND_COPY is set then the 'ptr' is
+	 * used.
+	 */
+	union
+	{
+		void *ptr;
+		u64 data;
+	};
 	u16		len;
 	/* Combination of bits from enum UVERBS_ATTR_F_XXXX */
 	u16		flags;
@@ -431,6 +441,17 @@ static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_att
 	return attr->obj_attr.uobject;
 }
 
+static inline int uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle,
+				      u16 idx)
+{
+	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
+
+	if (IS_ERR(attr))
+		return PTR_ERR(attr);
+
+	return attr->ptr_attr.len;
+}
+
 static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
 				 size_t idx, const void *from, size_t size)
 {
@@ -457,6 +478,18 @@ static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
 	return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
 }
 
+static inline const void *uverbs_attr_get_alloced_ptr(
+	const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
+{
+	const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
+
+	if (IS_ERR(attr))
+		return (void *)attr;
+
+	return uverbs_attr_ptr_is_inline(attr) ? &attr->ptr_attr.data :
+						 attr->ptr_attr.ptr;
+}
+
 static inline int _uverbs_copy_from(void *to,
 				    const struct uverbs_attr_bundle *attrs_bundle,
 				    size_t idx,

^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface
  2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
                   ` (19 preceding siblings ...)
  2018-06-17 10:00 ` [PATCH rdma-next v2 20/20] IB/mlx5: Expose DEVX tree Leon Romanovsky
@ 2018-06-18 22:05 ` Jason Gunthorpe
  2018-06-19  4:59   ` Leon Romanovsky
  20 siblings, 1 reply; 27+ messages in thread
From: Jason Gunthorpe @ 2018-06-18 22:05 UTC (permalink / raw)
  To: Leon Romanovsky
  Cc: Doug Ledford, Leon Romanovsky, RDMA mailing list,
	Joonas Lahtinen, Matan Barak, Yishai Hadas, Saeed Mahameed,
	linux-netdev

On Sun, Jun 17, 2018 at 12:59:46PM +0300, Leon Romanovsky wrote:
 
> Leon Romanovsky (2):
>   drm/i915: Move u64-to-ptr helpers to general header
>   kernel.h: Reuse u64_to_ptr macro to cast __user pointers

I dropped these since they are not needed by this series when using a
union.

> Matan Barak (5):
>   IB/uverbs: Export uverbs idr and fd types
>   IB/uverbs: Add PTR_IN attributes that are allocated/copied
>     automatically

Revised this one, as noted

>   IB/uverbs: Add a macro to define a type with no kernel known size
>   IB/uverbs: Allow an empty namespace in ioctl() framework
>   IB/uverbs: Refactor uverbs_finalize_objects

I put the above in a branch and can apply them if you ack my revisions..

>   net/mlx5_core: Prevent warns in dmesg upon firmware commands
>   IB/core: Improve uverbs_cleanup_ucontext algorithm

I dropped these two (they are linked), need comments addressed and
resent.

> Yishai Hadas (13):
>   net/mlx5: Expose DEVX ifc structures
>   IB/mlx5: Introduce DEVX
>   IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS
>   IB: Expose ib_ucontext from a given ib_uverbs_file
>   IB/mlx5: Add support for DEVX general command
>   IB/mlx5: Add obj create and destroy functionality
>   IB/mlx5: Add DEVX support for modify and query commands
>   IB/mlx5: Add support for DEVX query UAR
>   IB/mlx5: Add DEVX support for memory registration
>   IB/mlx5: Add DEVX query EQN support
>   IB/mlx5: Expose DEVX tree

I put these in a branch also and can apply them, but I need the first
two patches in the mlx5 core branch first please, thanks.

Since this requires so many core patches I think I prefer to merge the
mlx core branch then apply rather merge a branch.

Jason

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface
  2018-06-18 22:05 ` [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Jason Gunthorpe
@ 2018-06-19  4:59   ` Leon Romanovsky
  2018-06-19 16:46     ` Leon Romanovsky
  0 siblings, 1 reply; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-19  4:59 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Doug Ledford, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

[-- Attachment #1: Type: text/plain, Size: 2765 bytes --]

On Mon, Jun 18, 2018 at 04:05:04PM -0600, Jason Gunthorpe wrote:
> On Sun, Jun 17, 2018 at 12:59:46PM +0300, Leon Romanovsky wrote:
>
> > Leon Romanovsky (2):
> >   drm/i915: Move u64-to-ptr helpers to general header
> >   kernel.h: Reuse u64_to_ptr macro to cast __user pointers
>
> I dropped these since they are not needed by this series when using a
> union.

No problem, it was my idea to reuse existing macro, before it was
hard-coded implementation, but union makes it cleaner.

>
> > Matan Barak (5):
> >   IB/uverbs: Export uverbs idr and fd types
> >   IB/uverbs: Add PTR_IN attributes that are allocated/copied
> >     automatically
>
> Revised this one, as noted

Thanks

>
> >   IB/uverbs: Add a macro to define a type with no kernel known size
> >   IB/uverbs: Allow an empty namespace in ioctl() framework
> >   IB/uverbs: Refactor uverbs_finalize_objects
>
> I put the above in a branch and can apply them if you ack my revisions..
>

Except the line "return (void *)attr;", which should be "return ERR_CAST(attr);"
everything looks reasonable. I didn't test it, but I'm not worried, we will have
enough time to fix if needed.

> >   net/mlx5_core: Prevent warns in dmesg upon firmware commands
> >   IB/core: Improve uverbs_cleanup_ucontext algorithm
>
> I dropped these two (they are linked), need comments addressed and
> resent.

They are linked only logically, the second patch will trigger warning
which is suppressed by first patch. So actually mlx5-net branch will have
only first patch "net/mlx5_core: Prevent warns in dmesg upon firmware commands"
and you will apply "IB/core: Improve uverbs_cleanup_ucontext algorithm" in
your rdma-next.

>
> > Yishai Hadas (13):
> >   net/mlx5: Expose DEVX ifc structures
> >   IB/mlx5: Introduce DEVX
> >   IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS
> >   IB: Expose ib_ucontext from a given ib_uverbs_file
> >   IB/mlx5: Add support for DEVX general command
> >   IB/mlx5: Add obj create and destroy functionality
> >   IB/mlx5: Add DEVX support for modify and query commands
> >   IB/mlx5: Add support for DEVX query UAR
> >   IB/mlx5: Add DEVX support for memory registration
> >   IB/mlx5: Add DEVX query EQN support
> >   IB/mlx5: Expose DEVX tree
>
> I put these in a branch also and can apply them, but I need the first
> two patches in the mlx5 core branch first please, thanks.
>
> Since this requires so many core patches I think I prefer to merge the
> mlx core branch then apply rather merge a branch.

So to summarize, I'm applying those three patches to mlx5-next:
 * net/mlx5_core: Prevent warns in dmesg upon firmware commands
 * net/mlx5: Expose DEVX ifc structures
 * IB/mlx5: Introduce DEVX

And resend:
 * IB/core: Improve uverbs_cleanup_ucontext algorithm

Thanks

>
> Jason

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface
  2018-06-19  4:59   ` Leon Romanovsky
@ 2018-06-19 16:46     ` Leon Romanovsky
  0 siblings, 0 replies; 27+ messages in thread
From: Leon Romanovsky @ 2018-06-19 16:46 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Doug Ledford, RDMA mailing list, Joonas Lahtinen, Matan Barak,
	Yishai Hadas, Saeed Mahameed, linux-netdev

[-- Attachment #1: Type: text/plain, Size: 3184 bytes --]

On Tue, Jun 19, 2018 at 07:59:30AM +0300, Leon Romanovsky wrote:
> On Mon, Jun 18, 2018 at 04:05:04PM -0600, Jason Gunthorpe wrote:
> > On Sun, Jun 17, 2018 at 12:59:46PM +0300, Leon Romanovsky wrote:
> >
> > > Leon Romanovsky (2):
> > >   drm/i915: Move u64-to-ptr helpers to general header
> > >   kernel.h: Reuse u64_to_ptr macro to cast __user pointers
> >
> > I dropped these since they are not needed by this series when using a
> > union.
>
> No problem, it was my idea to reuse existing macro, before it was
> hard-coded implementation, but union makes it cleaner.
>
> >
> > > Matan Barak (5):
> > >   IB/uverbs: Export uverbs idr and fd types
> > >   IB/uverbs: Add PTR_IN attributes that are allocated/copied
> > >     automatically
> >
> > Revised this one, as noted
>
> Thanks
>
> >
> > >   IB/uverbs: Add a macro to define a type with no kernel known size
> > >   IB/uverbs: Allow an empty namespace in ioctl() framework
> > >   IB/uverbs: Refactor uverbs_finalize_objects
> >
> > I put the above in a branch and can apply them if you ack my revisions..
> >
>
> Except the line "return (void *)attr;", which should be "return ERR_CAST(attr);"
> everything looks reasonable. I didn't test it, but I'm not worried, we will have
> enough time to fix if needed.
>
> > >   net/mlx5_core: Prevent warns in dmesg upon firmware commands
> > >   IB/core: Improve uverbs_cleanup_ucontext algorithm
> >
> > I dropped these two (they are linked), need comments addressed and
> > resent.
>
> They are linked only logically, the second patch will trigger warning
> which is suppressed by first patch. So actually mlx5-net branch will have
> only first patch "net/mlx5_core: Prevent warns in dmesg upon firmware commands"
> and you will apply "IB/core: Improve uverbs_cleanup_ucontext algorithm" in
> your rdma-next.
>
> >
> > > Yishai Hadas (13):
> > >   net/mlx5: Expose DEVX ifc structures
> > >   IB/mlx5: Introduce DEVX
> > >   IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS
> > >   IB: Expose ib_ucontext from a given ib_uverbs_file
> > >   IB/mlx5: Add support for DEVX general command
> > >   IB/mlx5: Add obj create and destroy functionality
> > >   IB/mlx5: Add DEVX support for modify and query commands
> > >   IB/mlx5: Add support for DEVX query UAR
> > >   IB/mlx5: Add DEVX support for memory registration
> > >   IB/mlx5: Add DEVX query EQN support
> > >   IB/mlx5: Expose DEVX tree
> >
> > I put these in a branch also and can apply them, but I need the first
> > two patches in the mlx5 core branch first please, thanks.
> >
> > Since this requires so many core patches I think I prefer to merge the
> > mlx core branch then apply rather merge a branch.
>
> So to summarize, I'm applying those three patches to mlx5-next:
>  * net/mlx5_core: Prevent warns in dmesg upon firmware commands
>  * net/mlx5: Expose DEVX ifc structures
>  * IB/mlx5: Introduce DEVX

Updated mlx5-next with two patches and squashed ifc and commands bits
from third commit into second one.

>
> And resend:
>  * IB/core: Improve uverbs_cleanup_ucontext algorithm
>

Resent.

> Thanks
>
> >
> > Jason



[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2018-06-19 16:46 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-17  9:59 [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Leon Romanovsky
2018-06-17  9:59 ` [PATCH mlx5-next v2 01/20] net/mlx5_core: Prevent warns in dmesg upon firmware commands Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 02/20] drm/i915: Move u64-to-ptr helpers to general header Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 03/20] kernel.h: Reuse u64_to_ptr macro to cast __user pointers Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 04/20] IB/uverbs: Export uverbs idr and fd types Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 05/20] IB/uverbs: Refactor uverbs_finalize_objects Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 06/20] IB/uverbs: Add PTR_IN attributes that are allocated/copied automatically Leon Romanovsky
2018-06-18 20:48   ` Jason Gunthorpe
2018-06-17  9:59 ` [PATCH rdma-next v2 07/20] IB/uverbs: Add a macro to define a type with no kernel known size Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 08/20] IB/uverbs: Allow an empty namespace in ioctl() framework Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 09/20] IB/core: Improve uverbs_cleanup_ucontext algorithm Leon Romanovsky
2018-06-17 19:51   ` Jason Gunthorpe
2018-06-18 11:27     ` Yishai Hadas
2018-06-17  9:59 ` [PATCH mlx5-next v2 10/20] net/mlx5: Expose DEVX ifc structures Leon Romanovsky
2018-06-17  9:59 ` [PATCH mlx5-next v2 11/20] IB/mlx5: Introduce DEVX Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 12/20] IB/core: Introduce DECLARE_UVERBS_GLOBAL_METHODS Leon Romanovsky
2018-06-17  9:59 ` [PATCH rdma-next v2 13/20] IB: Expose ib_ucontext from a given ib_uverbs_file Leon Romanovsky
2018-06-17 10:00 ` [PATCH rdma-next v2 14/20] IB/mlx5: Add support for DEVX general command Leon Romanovsky
2018-06-17 10:00 ` [PATCH rdma-next v2 15/20] IB/mlx5: Add obj create and destroy functionality Leon Romanovsky
2018-06-17 10:00 ` [PATCH mlx5-next v2 16/20] IB/mlx5: Add DEVX support for modify and query commands Leon Romanovsky
2018-06-17 10:00 ` [PATCH rdma-next v2 17/20] IB/mlx5: Add support for DEVX query UAR Leon Romanovsky
2018-06-17 10:00 ` [PATCH mlx5-next v2 18/20] IB/mlx5: Add DEVX support for memory registration Leon Romanovsky
2018-06-17 10:00 ` [PATCH rdma-next v2 19/20] IB/mlx5: Add DEVX query EQN support Leon Romanovsky
2018-06-17 10:00 ` [PATCH rdma-next v2 20/20] IB/mlx5: Expose DEVX tree Leon Romanovsky
2018-06-18 22:05 ` [PATCH rdma-next v2 00/20] Introduce mlx5 DEVX interface Jason Gunthorpe
2018-06-19  4:59   ` Leon Romanovsky
2018-06-19 16:46     ` Leon Romanovsky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).