diff mbox series

[rdma-core,3/6] verbs: Make ibv_query_port extendable

Message ID 1545585297-6677-4-git-send-email-yishaih@mellanox.com (mailing list archive)
State Not Applicable
Headers show
Series verbs: Expose the IBTA port CapabilityMask2 | expand

Commit Message

Yishai Hadas Dec. 23, 2018, 5:14 p.m. UTC
From: Jason Gunthorpe <jgg@mellanox.com>

To be able to add new fields to the end of the struct without breaking
the ABI introduce a new query function that takes the length of the
struct as an argument and have the inline wrapper preserve the user API.

Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
---
 libibverbs/device.c       |  8 +++++++
 libibverbs/dummy_ops.c    |  2 +-
 libibverbs/ibverbs.h      |  2 ++
 libibverbs/verbs.c        | 53 +++++++++++++++++++++++++++++++++++++++++++++--
 libibverbs/verbs.h        | 27 ++++++++++++++++++------
 providers/bnxt_re/verbs.c |  1 -
 6 files changed, 83 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/libibverbs/device.c b/libibverbs/device.c
index 1fed29b..d710513 100644
--- a/libibverbs/device.c
+++ b/libibverbs/device.c
@@ -306,6 +306,14 @@  err_free:
 static void set_lib_ops(struct verbs_context *vctx)
 {
 	vctx->create_cq_ex = __lib_ibv_create_cq_ex;
+
+	/*
+	 * The compat symver entry point behaves identically to what used to
+	 * be pointed to by _compat_query_port.
+	 */
+#undef ibv_query_port
+	vctx->context.ops._compat_query_port = ibv_query_port;
+	vctx->query_port = __lib_query_port;
 }
 
 struct ibv_context *verbs_open_device(struct ibv_device *device, void *private_data)
diff --git a/libibverbs/dummy_ops.c b/libibverbs/dummy_ops.c
index a5e9380..c861c3a 100644
--- a/libibverbs/dummy_ops.c
+++ b/libibverbs/dummy_ops.c
@@ -616,7 +616,7 @@  void verbs_set_ops(struct verbs_context *vctx,
 	SET_OP(ctx, post_srq_recv);
 	SET_PRIV_OP(ctx, query_device);
 	SET_OP(vctx, query_device_ex);
-	SET_PRIV_OP(ctx, query_port);
+	SET_PRIV_OP_IC(ctx, query_port);
 	SET_PRIV_OP(ctx, query_qp);
 	SET_OP(vctx, query_rt_values);
 	SET_OP(vctx, read_counters);
diff --git a/libibverbs/ibverbs.h b/libibverbs/ibverbs.h
index 36e29a6..6e4cff4 100644
--- a/libibverbs/ibverbs.h
+++ b/libibverbs/ibverbs.h
@@ -58,6 +58,8 @@  int ibverbs_get_device_list(struct list_head *list);
 int ibverbs_init(void);
 void ibverbs_device_put(struct ibv_device *dev);
 void ibverbs_device_hold(struct ibv_device *dev);
+int __lib_query_port(struct ibv_context *context, uint8_t port_num,
+		     struct ibv_port_attr *port_attr, size_t port_attr_len);
 
 #ifdef _STATIC_LIBRARY_BUILD_
 static inline void load_drivers(void)
diff --git a/libibverbs/verbs.c b/libibverbs/verbs.c
index 5edd1bb..3540ef2 100644
--- a/libibverbs/verbs.c
+++ b/libibverbs/verbs.c
@@ -145,12 +145,61 @@  LATEST_SYMVER_FUNC(ibv_query_device, 1_1, "IBVERBS_1.1",
 	return get_ops(context)->query_device(context, device_attr);
 }
 
+int __lib_query_port(struct ibv_context *context, uint8_t port_num,
+		     struct ibv_port_attr *port_attr, size_t port_attr_len)
+{
+	/* Don't expose this mess to the provider, provide a large enough
+	 * temporary buffer if the user buffer is too small.
+	 */
+	if (port_attr_len < sizeof(struct ibv_port_attr)) {
+		struct ibv_port_attr tmp_attr = {};
+		int rc;
+
+		rc = get_ops(context)->query_port(context, port_num,
+						    &tmp_attr);
+		if (rc)
+			return rc;
+
+		memcpy(port_attr, &tmp_attr, port_attr_len);
+		return 0;
+	}
+
+	memset(port_attr, 0, port_attr_len);
+	return get_ops(context)->query_port(context, port_num, port_attr);
+}
+
+struct _compat_ibv_port_attr {
+	enum ibv_port_state state;
+	enum ibv_mtu max_mtu;
+	enum ibv_mtu active_mtu;
+	int gid_tbl_len;
+	uint32_t port_cap_flags;
+	uint32_t max_msg_sz;
+	uint32_t bad_pkey_cntr;
+	uint32_t qkey_viol_cntr;
+	uint16_t pkey_tbl_len;
+	uint16_t lid;
+	uint16_t sm_lid;
+	uint8_t lmc;
+	uint8_t max_vl_num;
+	uint8_t sm_sl;
+	uint8_t subnet_timeout;
+	uint8_t init_type_reply;
+	uint8_t active_width;
+	uint8_t active_speed;
+	uint8_t phys_state;
+	uint8_t link_layer;
+	uint8_t flags;
+};
+
 LATEST_SYMVER_FUNC(ibv_query_port, 1_1, "IBVERBS_1.1",
 		   int,
 		   struct ibv_context *context, uint8_t port_num,
-		   struct ibv_port_attr *port_attr)
+		   struct _compat_ibv_port_attr *port_attr)
 {
-	return get_ops(context)->query_port(context, port_num, port_attr);
+	return __lib_query_port(context, port_num,
+				(struct ibv_port_attr *)port_attr,
+				sizeof(*port_attr));
 }
 
 LATEST_SYMVER_FUNC(ibv_query_gid, 1_1, "IBVERBS_1.1",
diff --git a/libibverbs/verbs.h b/libibverbs/verbs.h
index caf78f4..4851c72 100644
--- a/libibverbs/verbs.h
+++ b/libibverbs/verbs.h
@@ -1661,9 +1661,12 @@  struct ibv_device {
 	char			ibdev_path[IBV_SYSFS_PATH_MAX];
 };
 
+struct _compat_ibv_port_attr;
 struct ibv_context_ops {
 	void *(*_compat_query_device)(void);
-	void *(*_compat_query_port)(void);
+	int (*_compat_query_port)(struct ibv_context *context,
+				  uint8_t port_num,
+				  struct _compat_ibv_port_attr *port_attr);
 	void *(*_compat_alloc_pd)(void);
 	void *(*_compat_dealloc_pd)(void);
 	void *(*_compat_reg_mr)(void);
@@ -1786,6 +1789,9 @@  struct ibv_values_ex {
 
 struct verbs_context {
 	/*  "grows up" - new fields go here */
+	int (*query_port)(struct ibv_context *context, uint8_t port_num,
+			  struct ibv_port_attr *port_attr,
+			  size_t port_attr_len);
 	int (*advise_mr)(struct ibv_pd *pd,
 			 enum ibv_advise_mr_advice advice,
 			 uint32_t flags,
@@ -1997,17 +2003,26 @@  int ibv_query_device(struct ibv_context *context,
  * ibv_query_port - Get port properties
  */
 int ibv_query_port(struct ibv_context *context, uint8_t port_num,
-		   struct ibv_port_attr *port_attr);
+		   struct _compat_ibv_port_attr *port_attr);
 
 static inline int ___ibv_query_port(struct ibv_context *context,
 				    uint8_t port_num,
 				    struct ibv_port_attr *port_attr)
 {
-	/* For compatibility when running with old libibverbs */
-	port_attr->link_layer = IBV_LINK_LAYER_UNSPECIFIED;
-	port_attr->flags      = 0;
+	struct verbs_context *vctx = verbs_get_ctx_op(context, query_port);
 
-	return ibv_query_port(context, port_num, port_attr);
+	if (!vctx) {
+		int rc;
+
+		memset(port_attr, 0, sizeof(*port_attr));
+
+		rc = ibv_query_port(context, port_num,
+				    (struct _compat_ibv_port_attr *)port_attr);
+		return rc;
+	}
+
+	return vctx->query_port(context, port_num, port_attr,
+				sizeof(*port_attr));
 }
 
 #define ibv_query_port(context, port_num, port_attr) \
diff --git a/providers/bnxt_re/verbs.c b/providers/bnxt_re/verbs.c
index 39b29b0..7786d24 100644
--- a/providers/bnxt_re/verbs.c
+++ b/providers/bnxt_re/verbs.c
@@ -74,7 +74,6 @@  int bnxt_re_query_port(struct ibv_context *ibvctx, uint8_t port,
 {
 	struct ibv_query_port cmd;
 
-	memset(port_attr, 0, sizeof(struct ibv_port_attr));
 	return ibv_cmd_query_port(ibvctx, port, port_attr, &cmd, sizeof(cmd));
 }