Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/ucma: Support write an event into a CM

Enable user-space to inject an event into a CM through it's event
channel. Two new events are added and supported: RDMA_CM_EVENT_USER and
RDMA_CM_EVENT_INTERNAL. With these 2 events a new event parameter "arg"
is supported, which is passed from sender to receiver transparently.

With this feature an application is able to write an event into a CM
channel with a new user-space rdmacm API. For example thread T1 could
write an event with the API:
rdma_write_cm_event(cm_id, RDMA_CM_EVENT_USER, status, arg);
and thread T2 could receive the event with rdma_get_cm_event().

Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Reviewed-by: Vlad Dumitrescu <vdumitrescu@nvidia.com>
Link: https://patch.msgid.link/fdf49d0b17a45933c5d8c1d90605c9447d9a3c73.1751279794.git.leonro@nvidia.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>

authored by

Mark Zhang and committed by
Leon Romanovsky
a3c9d0fc 810f874e

+70 -3
+51 -1
drivers/infiniband/core/ucma.c
··· 1745 1745 return ret; 1746 1746 } 1747 1747 1748 + static ssize_t ucma_write_cm_event(struct ucma_file *file, 1749 + const char __user *inbuf, int in_len, 1750 + int out_len) 1751 + { 1752 + struct rdma_ucm_write_cm_event cmd; 1753 + struct rdma_cm_event event = {}; 1754 + struct ucma_event *uevent; 1755 + struct ucma_context *ctx; 1756 + int ret = 0; 1757 + 1758 + if (copy_from_user(&cmd, inbuf, sizeof(cmd))) 1759 + return -EFAULT; 1760 + 1761 + if ((cmd.event != RDMA_CM_EVENT_USER) && 1762 + (cmd.event != RDMA_CM_EVENT_INTERNAL)) 1763 + return -EINVAL; 1764 + 1765 + ctx = ucma_get_ctx(file, cmd.id); 1766 + if (IS_ERR(ctx)) 1767 + return PTR_ERR(ctx); 1768 + 1769 + event.event = cmd.event; 1770 + event.status = cmd.status; 1771 + event.param.arg = cmd.param.arg; 1772 + 1773 + uevent = kzalloc(sizeof(*uevent), GFP_KERNEL); 1774 + if (!uevent) { 1775 + ret = -ENOMEM; 1776 + goto out; 1777 + } 1778 + 1779 + uevent->ctx = ctx; 1780 + uevent->resp.uid = ctx->uid; 1781 + uevent->resp.id = ctx->id; 1782 + uevent->resp.event = event.event; 1783 + uevent->resp.status = event.status; 1784 + memcpy(uevent->resp.param.arg32, &event.param.arg, 1785 + sizeof(event.param.arg)); 1786 + 1787 + mutex_lock(&ctx->file->mut); 1788 + list_add_tail(&uevent->list, &ctx->file->event_list); 1789 + mutex_unlock(&ctx->file->mut); 1790 + wake_up_interruptible(&ctx->file->poll_wait); 1791 + 1792 + out: 1793 + ucma_put_ctx(ctx); 1794 + return ret; 1795 + } 1796 + 1748 1797 static ssize_t (*ucma_cmd_table[])(struct ucma_file *file, 1749 1798 const char __user *inbuf, 1750 1799 int in_len, int out_len) = { ··· 1820 1771 [RDMA_USER_CM_CMD_BIND] = ucma_bind, 1821 1772 [RDMA_USER_CM_CMD_RESOLVE_ADDR] = ucma_resolve_addr, 1822 1773 [RDMA_USER_CM_CMD_JOIN_MCAST] = ucma_join_multicast, 1823 - [RDMA_USER_CM_CMD_RESOLVE_IB_SERVICE] = ucma_resolve_ib_service 1774 + [RDMA_USER_CM_CMD_RESOLVE_IB_SERVICE] = ucma_resolve_ib_service, 1775 + [RDMA_USER_CM_CMD_WRITE_CM_EVENT] = ucma_write_cm_event, 1824 1776 }; 1825 1777 1826 1778 static ssize_t ucma_write(struct file *filp, const char __user *buf,
+4 -1
include/rdma/rdma_cm.h
··· 35 35 RDMA_CM_EVENT_ADDR_CHANGE, 36 36 RDMA_CM_EVENT_TIMEWAIT_EXIT, 37 37 RDMA_CM_EVENT_ADDRINFO_RESOLVED, 38 - RDMA_CM_EVENT_ADDRINFO_ERROR 38 + RDMA_CM_EVENT_ADDRINFO_ERROR, 39 + RDMA_CM_EVENT_USER, 40 + RDMA_CM_EVENT_INTERNAL, 39 41 }; 40 42 41 43 const char *__attribute_const__ rdma_event_msg(enum rdma_cm_event_type event); ··· 100 98 union { 101 99 struct rdma_conn_param conn; 102 100 struct rdma_ud_param ud; 101 + u64 arg; 103 102 } param; 104 103 struct rdma_ucm_ece ece; 105 104 };
+15 -1
include/uapi/rdma/rdma_user_cm.h
··· 68 68 RDMA_USER_CM_CMD_BIND, 69 69 RDMA_USER_CM_CMD_RESOLVE_ADDR, 70 70 RDMA_USER_CM_CMD_JOIN_MCAST, 71 - RDMA_USER_CM_CMD_RESOLVE_IB_SERVICE 71 + RDMA_USER_CM_CMD_RESOLVE_IB_SERVICE, 72 + RDMA_USER_CM_CMD_WRITE_CM_EVENT, 72 73 }; 73 74 74 75 /* See IBTA Annex A11, servies ID bytes 4 & 5 */ ··· 305 304 union { 306 305 struct rdma_ucm_conn_param conn; 307 306 struct rdma_ucm_ud_param ud; 307 + __u32 arg32[2]; 308 308 } param; 309 309 __u32 reserved; 310 310 struct rdma_ucm_ece ece; ··· 363 361 struct rdma_ucm_resolve_ib_service { 364 362 __u32 id; 365 363 struct rdma_ucm_ib_service ibs; 364 + }; 365 + 366 + struct rdma_ucm_write_cm_event { 367 + __u32 id; 368 + __u32 reserved; 369 + __u32 event; 370 + __u32 status; 371 + union { 372 + struct rdma_ucm_conn_param conn; 373 + struct rdma_ucm_ud_param ud; 374 + __u64 arg; 375 + } param; 366 376 }; 367 377 #endif /* RDMA_USER_CM_H */