@@ -60,7 +60,7 @@ static int ibv_icmd_create_cq(struct ibv_context *context, int cqe,
switch (execute_ioctl_fallback(cq->context, create_cq, cmdb, &ret)) {
case TRY_WRITE: {
- DECLARE_LEGACY_UHW_BUFS(link, create_cq);
+ DECLARE_LEGACY_UHW_BUFS(link, IB_USER_VERBS_CMD_CREATE_CQ);
*req = (struct ib_uverbs_create_cq){
.user_handle = (uintptr_t)cq,
@@ -69,8 +69,7 @@ static int ibv_icmd_create_cq(struct ibv_context *context, int cqe,
.comp_channel = channel ? channel->fd : -1,
};
- ret = execute_write_bufs(IB_USER_VERBS_CMD_CREATE_CQ,
- cq->context, req, resp);
+ ret = execute_write_bufs(cq->context, req, resp);
if (ret)
return ret;
@@ -80,7 +79,8 @@ static int ibv_icmd_create_cq(struct ibv_context *context, int cqe,
return 0;
}
case TRY_WRITE_EX: {
- DECLARE_LEGACY_UHW_BUFS_EX(link, create_cq);
+ DECLARE_LEGACY_UHW_BUFS_EX(link,
+ IB_USER_VERBS_EX_CMD_CREATE_CQ);
*req = (struct ib_uverbs_ex_create_cq){
.user_handle = (uintptr_t)cq,
@@ -90,8 +90,7 @@ static int ibv_icmd_create_cq(struct ibv_context *context, int cqe,
.flags = flags,
};
- ret = execute_write_bufs_ex(IB_USER_VERBS_EX_CMD_CREATE_CQ,
- cq->context, req, resp);
+ ret = execute_write_bufs_ex(cq->context, req);
if (ret)
return ret;
@@ -152,7 +151,7 @@ int ibv_cmd_destroy_cq(struct ibv_cq *cq)
{
DECLARE_FBCMD_BUFFER(cmdb, UVERBS_OBJECT_CQ, UVERBS_METHOD_CQ_DESTROY, 2,
NULL);
- DECLARE_LEGACY_CORE_BUFS(destroy_cq);
+ DECLARE_LEGACY_CORE_BUFS(IB_USER_VERBS_CMD_DESTROY_CQ);
int ret;
fill_attr_out_ptr(cmdb, UVERBS_ATTR_DESTROY_CQ_RESP, &resp);
@@ -164,8 +163,7 @@ int ibv_cmd_destroy_cq(struct ibv_cq *cq)
.cq_handle = cq->handle,
};
- ret = execute_write(IB_USER_VERBS_CMD_DESTROY_CQ, cq->context,
- req, &resp);
+ ret = execute_write(cq->context, req, &resp);
break;
}
@@ -118,8 +118,9 @@ enum write_fallback _execute_ioctl_fallback(struct ibv_context *ctx,
* on the stack (if the driver didn't provide a UHW) or arranged to be
* directly before the UHW memory (see _write_set_uhw)
*/
-void *_write_get_req(struct ibv_command_buffer *link, void *onstack,
- size_t size)
+void *_write_get_req(struct ibv_command_buffer *link,
+ struct ib_uverbs_cmd_hdr *onstack, size_t size,
+ uint32_t cmdnum)
{
struct ib_uverbs_cmd_hdr *hdr;
@@ -137,13 +138,15 @@ void *_write_get_req(struct ibv_command_buffer *link, void *onstack,
hdr->in_words = __check_divide(size, 4);
}
+ hdr->command = cmdnum;
+
return hdr + 1;
}
-void *_write_get_req_ex(struct ibv_command_buffer *link, void *onstack,
- size_t size)
+void *_write_get_req_ex(struct ibv_command_buffer *link, struct ex_hdr *onstack,
+ size_t size, uint32_t cmdnum)
{
- struct _ib_ex_hdr *hdr;
+ struct ex_hdr *hdr;
size_t full_size = size + sizeof(*hdr);
if (link->uhw_in_idx != _UHW_NO_INDEX) {
@@ -160,6 +163,9 @@ void *_write_get_req_ex(struct ibv_command_buffer *link, void *onstack,
hdr->ex_hdr.provider_in_words = 0;
}
+ hdr->hdr.command = IB_USER_VERBS_CMD_FLAG_EXTENDED | cmdnum;
+ hdr->ex_hdr.cmd_hdr_reserved = 0;
+
return hdr + 1;
}
@@ -186,7 +192,7 @@ void *_write_get_resp(struct ibv_command_buffer *link,
}
void *_write_get_resp_ex(struct ibv_command_buffer *link,
- struct _ib_ex_hdr *hdr, void *onstack,
+ struct ex_hdr *hdr, void *onstack,
size_t resp_size)
{
void *resp_start;
@@ -206,51 +212,59 @@ void *_write_get_resp_ex(struct ibv_command_buffer *link,
hdr->ex_hdr.provider_out_words = 0;
}
+ hdr->ex_hdr.response = ioctl_ptr_to_u64(resp_start);
+
return resp_start;
}
-int _execute_write_raw(unsigned int cmdnum, struct ibv_context *ctx,
- struct ib_uverbs_cmd_hdr *hdr, void *resp)
+int _execute_write_raw(struct ibv_context *ctx, struct ib_uverbs_cmd_hdr *hdr,
+ void *resp)
{
- hdr->command = cmdnum;
-
/*
* Users assumes the stack buffer is zeroed before passing to the
* kernel for writing.
*/
- memset(resp, 0, hdr->out_words * 4);
+ if (resp) {
+ /*
+ * The helper macros prove the response is at offset 0 of the
+ * request.
+ */
+ uint64_t *response = (uint64_t *)(hdr + 1);
+
+ *response = ioctl_ptr_to_u64(resp);
+ memset(resp, 0, hdr->out_words * 4);
+ }
if (write(ctx->cmd_fd, hdr, hdr->in_words * 4) != hdr->in_words * 4)
return errno;
- VALGRIND_MAKE_MEM_DEFINED(resp, hdr->out_words * 4);
+ if (resp)
+ VALGRIND_MAKE_MEM_DEFINED(resp, hdr->out_words * 4);
return 0;
}
-int _execute_write_raw_ex(uint32_t cmdnum, struct ibv_context *ctx,
- struct _ib_ex_hdr *hdr, void *resp)
+int _execute_write_raw_ex(struct ibv_context *ctx, struct ex_hdr *hdr)
{
size_t write_bytes =
sizeof(*hdr) +
(hdr->hdr.in_words + hdr->ex_hdr.provider_in_words) * 8;
size_t resp_bytes =
(hdr->hdr.out_words + hdr->ex_hdr.provider_out_words) * 8;
-
- hdr->hdr.command = IB_USER_VERBS_CMD_FLAG_EXTENDED | cmdnum;
- hdr->ex_hdr.cmd_hdr_reserved = 0;
- hdr->ex_hdr.response = ioctl_ptr_to_u64(resp);
+ void *resp = (void *)(uintptr_t)hdr->ex_hdr.response;
/*
* Users assumes the stack buffer is zeroed before passing to the
* kernel for writing.
*/
- memset(resp, 0, resp_bytes);
+ if (resp)
+ memset(resp, 0, resp_bytes);
if (write(ctx->cmd_fd, hdr, write_bytes) != write_bytes)
return errno;
- VALGRIND_MAKE_MEM_DEFINED(resp, resp_bytes);
+ if (resp)
+ VALGRIND_MAKE_MEM_DEFINED(resp, resp_bytes);
return 0;
}
@@ -45,80 +45,49 @@ static inline struct ib_uverbs_cmd_hdr *get_req_hdr(void *req)
return ((struct ib_uverbs_cmd_hdr *)req) - 1;
}
-struct _ib_ex_hdr {
- struct ib_uverbs_cmd_hdr hdr;
- struct ib_uverbs_ex_cmd_hdr ex_hdr;
-};
-
-static inline struct _ib_ex_hdr *get_req_hdr_ex(void *req)
+static inline struct ex_hdr *get_req_hdr_ex(void *req)
{
- return ((struct _ib_ex_hdr *)req) - 1;
+ return ((struct ex_hdr *)req) - 1;
}
-/*
- * When using these new interfaces the kernel UAPI structs 'ib_uverbs_*' are
- * used, not the structs from kern-abi.h. The only difference between the two
- * is the inclusion of the header in the kern-abi.h struct. This macro creates
- * memory on the stack that includes both the header and the struct.
- */
-#define DECLARE_LEGACY_REQ_BUF_CORE(_name, _pattern) \
- struct { \
- struct ib_uverbs_cmd_hdr hdr; \
- struct ib_uverbs_##_pattern core_payload; \
- } _name
-
-#define DECLARE_LEGACY_REQ_BUF_CORE_EX(_name, _pattern) \
- struct { \
- struct ib_uverbs_cmd_hdr hdr; \
- struct ib_uverbs_ex_cmd_hdr ex_hdr; \
- struct ib_uverbs_ex_##_pattern core_payload; \
- } _name
-
-void *_write_get_req(struct ibv_command_buffer *link, void *onstack,
- size_t size);
-void *_write_get_req_ex(struct ibv_command_buffer *link, void *onstack,
- size_t size);
+void *_write_get_req(struct ibv_command_buffer *link,
+ struct ib_uverbs_cmd_hdr *onstack, size_t size,
+ uint32_t cmdnum);
+void *_write_get_req_ex(struct ibv_command_buffer *link, struct ex_hdr *onstack,
+ size_t size, uint32_t cmdnum);
void *_write_get_resp(struct ibv_command_buffer *link,
struct ib_uverbs_cmd_hdr *hdr, void *onstack,
size_t resp_size);
void *_write_get_resp_ex(struct ibv_command_buffer *link,
- struct _ib_ex_hdr *hdr, void *onstack,
+ struct ex_hdr *hdr, void *onstack,
size_t resp_size);
-#define DECLARE_LEGACY_REQ_BUF(_name, _link, _pattern) \
- DECLARE_LEGACY_REQ_BUF_CORE(__##_name##_onstack, _pattern); \
- struct ib_uverbs_##_pattern *_name = \
- _write_get_req(_link, &__##_name##_onstack, sizeof(*_name))
-
-#define DECLARE_LEGACY_REQ_BUF_EX(_name, _link, _pattern) \
- DECLARE_LEGACY_REQ_BUF_CORE_EX(__##_name##_onstack, _pattern); \
- struct ib_uverbs_ex_##_pattern *_name = \
- _write_get_req_ex(_link, &__##_name##_onstack, sizeof(*_name))
-
-#define DECLARE_LEGACY_RESP_BUF(_name, _link, _req, _pattern) \
- struct ib_uverbs_##_pattern##_resp __##_name##_onstack, \
- *_name = _write_get_resp(_link, get_req_hdr(_req), \
- &__##_name##_onstack, sizeof(*_name))
-
-#define DECLARE_LEGACY_RESP_BUF_EX(_name, _link, _req, _pattern) \
- struct ib_uverbs_ex_##_pattern##_resp __##_name##_onstack, \
- *_name = _write_get_resp_ex(_link, get_req_hdr_ex(_req), \
- &__##_name##_onstack, \
- sizeof(*_name))
-
/*
* This macro creates 'req' and 'resp' pointers in the local stack frame that
* point to the core code write command structures patterned off _pattern.
*
* This should be done before calling execute_write_bufs
*/
-#define DECLARE_LEGACY_UHW_BUFS(_link, _pattern) \
- DECLARE_LEGACY_REQ_BUF(req, _link, _pattern); \
- DECLARE_LEGACY_RESP_BUF(resp, _link, req, _pattern)
+#define DECLARE_LEGACY_UHW_BUFS(_link, _enum) \
+ IBV_ABI_REQ(_enum) __req_onstack; \
+ IBV_KABI_RESP(_enum) __resp_onstack; \
+ static_assert(offsetof(IBV_KABI_REQ(_enum), response) == 0, \
+ "Bad response offset"); \
+ IBV_KABI_REQ(_enum) *req = _write_get_req(_link, &__req_onstack.hdr, \
+ sizeof(*req), _enum); \
+ IBV_KABI_RESP(_enum) *resp = ({ \
+ void *_resp = _write_get_resp(_link, get_req_hdr(req), \
+ &__resp_onstack, sizeof(*resp)); \
+ _resp; \
+ })
-#define DECLARE_LEGACY_UHW_BUFS_EX(_link, _pattern) \
- DECLARE_LEGACY_REQ_BUF_EX(req, _link, _pattern); \
- DECLARE_LEGACY_RESP_BUF_EX(resp, _link, req, _pattern)
+#define DECLARE_LEGACY_UHW_BUFS_EX(_link, _enum) \
+ IBV_ABI_REQ(_enum) __req_onstack; \
+ IBV_KABI_RESP(_enum) __resp_onstack; \
+ IBV_KABI_REQ(_enum) *req = _write_get_req_ex( \
+ _link, &__req_onstack.hdr, sizeof(*req), _enum); \
+ IBV_KABI_RESP(_enum) *resp = _write_get_resp_ex( \
+ _link, get_req_hdr_ex(req), &__resp_onstack, sizeof(*resp))
/*
* This macro is used to implement the compatibility command call wrappers.
@@ -174,51 +143,68 @@ enum write_fallback _execute_ioctl_fallback(struct ibv_context *ctx,
_execute_ioctl_fallback(ctx, _CMD_BIT(cmd_name), cmdb, ret)
/* These helpers replace the raw write() and IBV_INIT_CMD macros */
-int _execute_write_raw(unsigned int cmdnum, struct ibv_context *ctx,
- struct ib_uverbs_cmd_hdr *req, void *resp);
+int _execute_write_raw(struct ibv_context *ctx, struct ib_uverbs_cmd_hdr *req,
+ void *resp);
/* For users of DECLARE_LEGACY_UHW_BUFS */
-#define execute_write_bufs(cmdnum, ctx, req, resp) \
- ({ \
- (req)->response = ioctl_ptr_to_u64(resp); \
- _execute_write_raw(cmdnum, ctx, get_req_hdr(req), resp); \
- })
+#define execute_write_bufs(ctx, req, resp) \
+ _execute_write_raw(ctx, get_req_hdr(req), resp)
-int _execute_write_raw_ex(uint32_t cmdnum, struct ibv_context *ctx,
- struct _ib_ex_hdr *req, void *resp);
+int _execute_write_raw_ex(struct ibv_context *ctx, struct ex_hdr *req);
/* For users of DECLARE_LEGACY_UHW_BUFS_EX */
-#define execute_write_bufs_ex(cmdnum, ctx, req, resp) \
- _execute_write_raw_ex(cmdnum, ctx, get_req_hdr_ex(req), resp)
-
-static inline int _execute_write(uint32_t cmdnum, struct ibv_context *ctx,
- void *req, size_t req_len, void *resp,
- size_t resp_len)
-{
- struct ib_uverbs_cmd_hdr *hdr = get_req_hdr(req);
-
- hdr->in_words = req_len / 4;
- hdr->out_words = resp_len / 4;
- return _execute_write_raw(cmdnum, ctx, hdr, resp);
-}
+#define execute_write_bufs_ex(ctx, req) \
+ _execute_write_raw_ex(ctx, get_req_hdr_ex(req))
/* For users with no possible UHW bufs. */
-#define DECLARE_LEGACY_CORE_BUFS(_pattern) \
- DECLARE_LEGACY_REQ_BUF_CORE(__req_onstack, _pattern); \
- struct ib_uverbs_##_pattern *const req = &__req_onstack.core_payload; \
- struct ib_uverbs_##_pattern##_resp resp
+#define DECLARE_LEGACY_CORE_BUFS(_enum) \
+ IBV_ABI_REQ(_enum) __req_onstack; \
+ IBV_KABI_RESP(_enum) resp; \
+ static_assert(offsetof(IBV_KABI_REQ(_enum), response) == 0, \
+ "Bad response offset"); \
+ IBV_KABI_REQ(_enum) *const req = ({ \
+ __req_onstack.hdr.command = _enum; \
+ __req_onstack.hdr.in_words = sizeof(__req_onstack) / 4; \
+ __req_onstack.hdr.out_words = sizeof(resp) / 4; \
+ &__req_onstack.core_payload; \
+ })
+#define DECLARE_LEGACY_CORE_REQ(_enum) \
+ IBV_ABI_REQ(_enum) __req_onstack; \
+ static_assert(sizeof(IBV_KABI_RESP(_enum)) == 0, \
+ "Method has a response!"); \
+ IBV_KABI_REQ(_enum) *const req = ({ \
+ __req_onstack.hdr.command = _enum; \
+ __req_onstack.hdr.in_words = sizeof(__req_onstack) / 4; \
+ __req_onstack.hdr.out_words = 0; \
+ &__req_onstack.core_payload; \
+ })
+
+#define DECLARE_LEGACY_CORE_BUFS_EX(_enum) \
+ IBV_ABI_REQ(_enum) __req_onstack; \
+ IBV_KABI_RESP(_enum) resp; \
+ IBV_KABI_REQ(_enum) *const req = ({ \
+ __req_onstack.hdr.hdr.command = \
+ IB_USER_VERBS_CMD_FLAG_EXTENDED | _enum; \
+ __req_onstack.hdr.hdr.in_words = \
+ (sizeof(__req_onstack) - sizeof(struct ex_hdr)) / 8; \
+ __req_onstack.hdr.hdr.out_words = sizeof(resp) / 8; \
+ __req_onstack.hdr.ex_hdr.cmd_hdr_reserved = 0; \
+ __req_onstack.hdr.ex_hdr.provider_in_words = 0; \
+ __req_onstack.hdr.ex_hdr.provider_out_words = 0; \
+ __req_onstack.hdr.ex_hdr.response = \
+ (sizeof(resp) == 0) ? 0 : ioctl_ptr_to_u64(&resp); \
+ &__req_onstack.core_payload; \
+ })
/*
* For users with no UHW bufs. To be used in conjunction with
* DECLARE_LEGACY_CORE_BUFS. req points to the core payload (with headroom for
* the header).
*/
-#define execute_write(cmdnum, ctx, req, resp) \
- ({ \
- (req)->response = ioctl_ptr_to_u64(resp); \
- _execute_write(cmdnum, ctx, req, sizeof(*req), resp, \
- sizeof(*resp)); \
- })
+#define execute_write(ctx, req, resp) \
+ _execute_write_raw(ctx, get_req_hdr(req), resp)
+#define execute_write_ex(ctx, req) \
+ _execute_write_raw_ex(ctx, get_req_hdr_ex(req))
/*
* These two macros are used only with execute_ioctl_fallback - they allow the
@@ -247,24 +233,20 @@ _execute_ioctl_only(struct ibv_context *context, struct ibv_command_buffer *cmd,
_execute_ioctl_only(ctx, cmdb, ret)
#undef execute_write_bufs
-static inline int execute_write_bufs(uint32_t cmdnum,
- struct ibv_context *ctx, void *req,
+static inline int execute_write_bufs(struct ibv_context *ctx, void *req,
void *resp)
{
return ENOSYS;
}
#undef execute_write_bufs_ex
-static inline int execute_write_bufs_ex(uint32_t cmdnum,
- struct ibv_context *ctx, void *req,
- void *resp)
+static inline int execute_write_bufs_ex(struct ibv_context *ctx, void *req)
{
return ENOSYS;
}
#undef execute_write
-static inline int execute_write(uint32_t cmdnum,
- struct ibv_context *ctx, void *req,
+static inline int execute_write(struct ibv_context *ctx, void *req,
void *resp)
{
return ENOSYS;