| /* | |
| * Copyright (c) 2018 Mellanox Technologies, Ltd. All rights reserved. | |
| * | |
| * This software is available to you under a choice of one of two | |
| * licenses. You may choose to be licensed under the terms of the GNU | |
| * General Public License (GPL) Version 2, available from the file | |
| * COPYING in the main directory of this source tree, or the | |
| * OpenIB.org BSD license below: | |
| * | |
| * Redistribution and use in source and binary forms, with or | |
| * without modification, are permitted provided that the following | |
| * conditions are met: | |
| * | |
| * - Redistributions of source code must retain the above | |
| * copyright notice, this list of conditions and the following | |
| * disclaimer. | |
| * | |
| * - Redistributions in binary form must reproduce the above | |
| * copyright notice, this list of conditions and the following | |
| * disclaimer in the documentation and/or other materials | |
| * provided with the distribution. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| * SOFTWARE. | |
| */ | |
| #ifndef __INFINIBAND_VERBS_WRITE_H | |
| #define __INFINIBAND_VERBS_WRITE_H | |
| #include <infiniband/cmd_ioctl.h> | |
| #include <infiniband/driver.h> | |
| #include <rdma/ib_user_verbs.h> | |
| #include <rdma/ib_user_ioctl_cmds.h> | |
| #include <stdbool.h> | |
| void *_write_get_req(struct ibv_command_buffer *link, | |
| struct ib_uverbs_cmd_hdr *onstack, size_t size); | |
| void *_write_get_req_ex(struct ibv_command_buffer *link, struct ex_hdr *onstack, | |
| size_t size); | |
| 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 ex_hdr *hdr, void *onstack, | |
| size_t resp_size); | |
| /* | |
| * 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, _enum) \ | |
| IBV_ABI_REQ(_enum) __req_onstack; \ | |
| IBV_KABI_RESP(_enum) __resp_onstack; \ | |
| IBV_KABI_REQ(_enum) *req = \ | |
| _write_get_req(_link, &__req_onstack.hdr, sizeof(*req)); \ | |
| IBV_KABI_RESP(_enum) *resp = ({ \ | |
| void *_resp = _write_get_resp( \ | |
| _link, \ | |
| &container_of(req, IBV_ABI_REQ(_enum), core_payload) \ | |
| ->hdr, \ | |
| &__resp_onstack, sizeof(*resp)); \ | |
| _resp; \ | |
| }) | |
| #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)); \ | |
| IBV_KABI_RESP(_enum) *resp = _write_get_resp_ex( \ | |
| _link, \ | |
| &container_of(req, IBV_ABI_REQ(_enum), core_payload)->hdr, \ | |
| &__resp_onstack, sizeof(*resp)) | |
| /* | |
| * This macro is used to implement the compatibility command call wrappers. | |
| * Compatibility calls do not accept a command_buffer, and cannot use the new | |
| * attribute id mechanism. They accept the legacy kern-abi.h structs that have | |
| * the embedded header. | |
| */ | |
| void _write_set_uhw(struct ibv_command_buffer *cmdb, const void *req, | |
| size_t core_req_size, size_t req_size, void *resp, | |
| size_t core_resp_size, size_t resp_size); | |
| #define DECLARE_CMD_BUFFER_COMPAT(_name, _object_id, _method_id, cmd, \ | |
| cmd_size, resp, resp_size) \ | |
| DECLARE_COMMAND_BUFFER(_name, _object_id, _method_id, 2); \ | |
| _write_set_uhw(_name, cmd, sizeof(*cmd), cmd_size, resp, \ | |
| sizeof(*resp), resp_size) | |
| #define DECLARE_CMD_BUFFER_LINK_COMPAT(_name, _object_id, _method_id, \ | |
| _link, cmd, cmd_size, \ | |
| resp, resp_size) \ | |
| DECLARE_COMMAND_BUFFER_LINK(_name, _object_id, _method_id, 2, _link); \ | |
| _write_set_uhw(_name, cmd, sizeof(*cmd), cmd_size, resp, \ | |
| sizeof(*resp), resp_size) | |
| /* | |
| * The fallback scheme keeps track of which ioctls succeed in a per-context | |
| * bitmap. If ENOTTY or EPROTONOSUPPORT is seen then the ioctl is never | |
| * retried. | |
| * | |
| * cmd_name should be the name of the function op from verbs_context_ops | |
| * that is being implemented. | |
| */ | |
| #define _CMD_BIT(cmd_name) \ | |
| (offsetof(struct verbs_context_ops, cmd_name) / sizeof(void *)) | |
| enum write_fallback { TRY_WRITE, TRY_WRITE_EX, ERROR, SUCCESS }; | |
| /* | |
| * This bitmask indicate the required behavior of execute_ioctl_fallback when | |
| * the ioctl is not supported. It is a priority list where the highest set bit | |
| * takes precedence. This approach simplifies the typical required control | |
| * flow of the user. | |
| */ | |
| static inline void fallback_require_ex(struct ibv_command_buffer *cmdb) | |
| { | |
| cmdb->fallback_require_ex = 1; | |
| } | |
| static inline void fallback_require_ioctl(struct ibv_command_buffer *cmdb) | |
| { | |
| cmdb->fallback_ioctl_only = 1; | |
| } | |
| enum write_fallback _check_legacy(struct ibv_command_buffer *cmdb, int *ret); | |
| enum write_fallback _execute_ioctl_fallback(struct ibv_context *ctx, | |
| unsigned int cmd_bit, | |
| struct ibv_command_buffer *cmdb, | |
| int *ret); | |
| #define execute_ioctl_fallback(ctx, cmd_name, cmdb, ret) \ | |
| _execute_ioctl_fallback(ctx, _CMD_BIT(cmd_name), cmdb, ret) | |
| /* | |
| * For write() only commands that have fixed core structures and may take uhw | |
| * driver data. The last arguments are the same ones passed into the typical | |
| * ibv_cmd_* function. execute_cmd_write deduces the length of the core | |
| * structure based on the KABI struct linked to the enum op code. | |
| */ | |
| int _execute_cmd_write(struct ibv_context *ctx, unsigned int write_method, | |
| void *req, size_t core_req_size, | |
| size_t req_size, void *resp, size_t core_resp_size, | |
| size_t resp_size); | |
| #define execute_cmd_write(ctx, enum, cmd, cmd_size, resp, resp_size) \ | |
| ({ \ | |
| (cmd)->core_payload.response = ioctl_ptr_to_u64(resp); \ | |
| _execute_cmd_write( \ | |
| ctx, enum, cmd + check_type(cmd, IBV_ABI_REQ(enum) *), \ | |
| sizeof(*(cmd)), cmd_size, \ | |
| resp + check_type(resp, IBV_KABI_RESP(enum) *), \ | |
| sizeof(*(resp)), resp_size); \ | |
| }) | |
| /* For write() commands that have no response */ | |
| #define execute_cmd_write_req(ctx, enum, cmd, cmd_size) \ | |
| ({ \ | |
| static_assert(sizeof(IBV_KABI_RESP(enum)) == 0, \ | |
| "Method has a response!"); \ | |
| _execute_cmd_write(ctx, enum, \ | |
| cmd + check_type(cmd, IBV_ABI_REQ(enum) *), \ | |
| sizeof(*(cmd)), cmd_size, NULL, 0, 0); \ | |
| }) | |
| /* | |
| * Execute a write command that does not have a uhw component. The cmd_size | |
| * and resp_size are the lengths of the core structure. This version is only | |
| * needed if the core structure ends in a flex array, as the internal sizeof() | |
| * in execute_cmd_write() will give the wrong size. | |
| */ | |
| #define execute_cmd_write_no_uhw(ctx, enum, cmd, cmd_size, resp, resp_size) \ | |
| ({ \ | |
| (cmd)->core_payload.response = ioctl_ptr_to_u64(resp); \ | |
| _execute_cmd_write( \ | |
| ctx, enum, cmd + check_type(cmd, IBV_ABI_REQ(enum) *), \ | |
| cmd_size, cmd_size, \ | |
| resp + check_type(resp, IBV_KABI_RESP(enum) *), \ | |
| resp_size, resp_size); \ | |
| }) | |
| /* | |
| * For users of DECLARE_LEGACY_UHW_BUFS, in this case the machinery has | |
| * already stored the full req/resp length in the hdr. | |
| */ | |
| #define execute_write_bufs(ctx, enum, req, resp) \ | |
| ({ \ | |
| IBV_ABI_REQ(enum) *_hdr = \ | |
| container_of(req, IBV_ABI_REQ(enum), core_payload); \ | |
| execute_cmd_write(ctx, enum, _hdr, _hdr->hdr.in_words * 4, \ | |
| resp, _hdr->hdr.out_words * 4); \ | |
| }) | |
| /* | |
| * For write() commands that use the _ex protocol. _full allows the caller to | |
| * specify all 4 sizes directly. This version is used when the core structs | |
| * end in a flex array. The normal and req versions are similar to write() and | |
| * deduce the length of the core struct from the enum. | |
| */ | |
| int _execute_cmd_write_ex(struct ibv_context *ctx, unsigned int write_method, | |
| struct ex_hdr *req, size_t core_req_size, | |
| size_t req_size, void *resp, size_t core_resp_size, | |
| size_t resp_size); | |
| #define execute_cmd_write_ex_full(ctx, enum, cmd, core_cmd_size, cmd_size, \ | |
| resp, core_resp_size, resp_size) \ | |
| _execute_cmd_write_ex( \ | |
| ctx, enum, &(cmd)->hdr + check_type(cmd, IBV_ABI_REQ(enum) *), \ | |
| core_cmd_size, cmd_size, \ | |
| resp + check_type(resp, IBV_KABI_RESP(enum) *), \ | |
| core_resp_size, resp_size) | |
| #define execute_cmd_write_ex(ctx, enum, cmd, cmd_size, resp, resp_size) \ | |
| execute_cmd_write_ex_full(ctx, enum, cmd, sizeof(*(cmd)), cmd_size, \ | |
| resp, sizeof(*(resp)), resp_size) | |
| #define execute_cmd_write_ex_req(ctx, enum, cmd, cmd_size) \ | |
| ({ \ | |
| static_assert(sizeof(IBV_KABI_RESP(enum)) == 0, \ | |
| "Method has a response!"); \ | |
| _execute_cmd_write_ex( \ | |
| ctx, enum, \ | |
| &(cmd)->hdr + check_type(cmd, IBV_ABI_REQ(enum) *), \ | |
| sizeof(*(cmd)), cmd_size, NULL, 0, 0); \ | |
| }) | |
| /* For users of DECLARE_LEGACY_UHW_BUFS_EX */ | |
| #define execute_write_bufs_ex(ctx, enum, req, resp) \ | |
| ({ \ | |
| IBV_ABI_REQ(enum) *_hdr = \ | |
| container_of(req, IBV_ABI_REQ(enum), core_payload); \ | |
| execute_cmd_write_ex( \ | |
| ctx, enum, _hdr, \ | |
| sizeof(*_hdr) + \ | |
| _hdr->hdr.ex_hdr.provider_in_words * 8, \ | |
| resp, \ | |
| sizeof(*(resp)) + \ | |
| _hdr->hdr.ex_hdr.provider_out_words * 8); \ | |
| }) | |
| /* | |
| * These two macros are used only with execute_ioctl_fallback - they allow the | |
| * IOCTL code to be elided by the compiler when disabled. | |
| */ | |
| #define DECLARE_FBCMD_BUFFER DECLARE_COMMAND_BUFFER_LINK | |
| /* | |
| * Munge the macros above to remove certain paths during compilation based on | |
| * the cmake flag. | |
| */ | |
| #if VERBS_IOCTL_ONLY | |
| static inline enum write_fallback | |
| _execute_ioctl_only(struct ibv_context *context, struct ibv_command_buffer *cmd, | |
| int *ret) | |
| { | |
| *ret = execute_ioctl(context, cmd); | |
| if (*ret) | |
| return ERROR; | |
| return SUCCESS; | |
| } | |
| #undef execute_ioctl_fallback | |
| #define execute_ioctl_fallback(ctx, cmd_name, cmdb, ret) \ | |
| _execute_ioctl_only(ctx, cmdb, ret) | |
| #undef execute_write_bufs | |
| static inline int execute_write_bufs(struct ibv_context *ctx, | |
| unsigned int write_command, void *req, | |
| void *resp) | |
| { | |
| return ENOSYS; | |
| } | |
| #undef execute_write_bufs_ex | |
| static inline int execute_write_bufs_ex(struct ibv_context *ctx, | |
| unsigned int write_command, void *req, | |
| void *resp) | |
| { | |
| return ENOSYS; | |
| } | |
| #endif | |
| #if VERBS_WRITE_ONLY | |
| static inline enum write_fallback | |
| _execute_write_only(struct ibv_context *context, struct ibv_command_buffer *cmd, | |
| int *ret) | |
| { | |
| /* | |
| * write only still has the command buffer, and the command buffer | |
| * carries the fallback guidance that we need to inspect. This is | |
| * written in this odd way so the compiler knows that SUCCESS is not a | |
| * possible return and optimizes accordingly. | |
| */ | |
| switch (_check_legacy(cmd, ret)) { | |
| case TRY_WRITE: | |
| return TRY_WRITE; | |
| case TRY_WRITE_EX: | |
| return TRY_WRITE_EX; | |
| default: | |
| return ERROR; | |
| } | |
| } | |
| #undef execute_ioctl_fallback | |
| #define execute_ioctl_fallback(ctx, cmd_name, cmdb, ret) \ | |
| _execute_write_only(ctx, cmdb, ret) | |
| #undef DECLARE_FBCMD_BUFFER | |
| #define DECLARE_FBCMD_BUFFER(_name, _object_id, _method_id, _num_attrs, _link) \ | |
| struct ibv_command_buffer _name[1] = { \ | |
| { \ | |
| .next = _link, \ | |
| .uhw_in_idx = _UHW_NO_INDEX, \ | |
| .uhw_out_idx = _UHW_NO_INDEX, \ | |
| }, \ | |
| } | |
| #endif | |
| extern bool verbs_allow_disassociate_destroy; | |
| /* | |
| * Return true if 'ret' indicates that a destroy operation has failed | |
| * and the function should exit. If the kernel destroy failure is being | |
| * ignored then this will set ret to 0, so the calling function appears to succeed. | |
| */ | |
| static inline bool verbs_is_destroy_err(int *ret) | |
| { | |
| if (*ret == EIO && verbs_allow_disassociate_destroy) { | |
| *ret = 0; | |
| return true; | |
| } | |
| return *ret != 0; | |
| } | |
| #endif |