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

IB/mad: Add user space RMPP support

Using the new registration mechanism, define a flag that indicates the
user wishes to process RMPP messages in user space rather than have
the kernel process them.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>

authored by

Ira Weiny and committed by
Roland Dreier
1471cb6c 0f29b46d

+89 -37
+52 -24
drivers/infiniband/core/mad.c
··· 283 283 goto error1; 284 284 } 285 285 } 286 + 286 287 /* Make sure class supplied is consistent with QP type */ 287 288 if (qp_type == IB_QPT_SMI) { 288 289 if ((mad_reg_req->mgmt_class != ··· 309 308 } else { 310 309 /* No registration request supplied */ 311 310 if (!send_handler) 311 + goto error1; 312 + if (registration_flags & IB_MAD_USER_RMPP) 312 313 goto error1; 313 314 } 314 315 ··· 910 907 return 0; 911 908 } 912 909 910 + int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent) 911 + { 912 + return agent->rmpp_version && !(agent->flags & IB_MAD_USER_RMPP); 913 + } 914 + EXPORT_SYMBOL(ib_mad_kernel_rmpp_agent); 915 + 913 916 struct ib_mad_send_buf * ib_create_send_mad(struct ib_mad_agent *mad_agent, 914 917 u32 remote_qpn, u16 pkey_index, 915 918 int rmpp_active, ··· 932 923 pad = get_pad_size(hdr_len, data_len); 933 924 message_size = hdr_len + data_len + pad; 934 925 935 - if ((!mad_agent->rmpp_version && 936 - (rmpp_active || message_size > sizeof(struct ib_mad))) || 937 - (!rmpp_active && message_size > sizeof(struct ib_mad))) 938 - return ERR_PTR(-EINVAL); 926 + if (ib_mad_kernel_rmpp_agent(mad_agent)) { 927 + if (!rmpp_active && message_size > sizeof(struct ib_mad)) 928 + return ERR_PTR(-EINVAL); 929 + } else 930 + if (rmpp_active || message_size > sizeof(struct ib_mad)) 931 + return ERR_PTR(-EINVAL); 939 932 940 933 size = rmpp_active ? hdr_len : sizeof(struct ib_mad); 941 934 buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); ··· 1191 1180 &mad_agent_priv->send_list); 1192 1181 spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 1193 1182 1194 - if (mad_agent_priv->agent.rmpp_version) { 1183 + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { 1195 1184 ret = ib_send_rmpp_mad(mad_send_wr); 1196 1185 if (ret >= 0 && ret != IB_RMPP_RESULT_CONSUMED) 1197 1186 ret = ib_send_mad(mad_send_wr); ··· 1741 1730 1742 1731 rmpp_mad = (struct ib_rmpp_mad *)mad_hdr; 1743 1732 return !mad_agent_priv->agent.rmpp_version || 1733 + !ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) || 1744 1734 !(ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & 1745 1735 IB_MGMT_RMPP_FLAG_ACTIVE) || 1746 1736 (rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA); ··· 1869 1857 1870 1858 INIT_LIST_HEAD(&mad_recv_wc->rmpp_list); 1871 1859 list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); 1872 - if (mad_agent_priv->agent.rmpp_version) { 1860 + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { 1873 1861 mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv, 1874 1862 mad_recv_wc); 1875 1863 if (!mad_recv_wc) { ··· 1884 1872 mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc); 1885 1873 if (!mad_send_wr) { 1886 1874 spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 1887 - ib_free_recv_mad(mad_recv_wc); 1888 - deref_mad_agent(mad_agent_priv); 1889 - return; 1875 + if (!ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent) 1876 + && ib_is_mad_class_rmpp(mad_recv_wc->recv_buf.mad->mad_hdr.mgmt_class) 1877 + && (ib_get_rmpp_flags(&((struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad)->rmpp_hdr) 1878 + & IB_MGMT_RMPP_FLAG_ACTIVE)) { 1879 + /* user rmpp is in effect 1880 + * and this is an active RMPP MAD 1881 + */ 1882 + mad_recv_wc->wc->wr_id = 0; 1883 + mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, 1884 + mad_recv_wc); 1885 + atomic_dec(&mad_agent_priv->refcount); 1886 + } else { 1887 + /* not user rmpp, revert to normal behavior and 1888 + * drop the mad */ 1889 + ib_free_recv_mad(mad_recv_wc); 1890 + deref_mad_agent(mad_agent_priv); 1891 + return; 1892 + } 1893 + } else { 1894 + ib_mark_mad_done(mad_send_wr); 1895 + spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 1896 + 1897 + /* Defined behavior is to complete response before request */ 1898 + mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf; 1899 + mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, 1900 + mad_recv_wc); 1901 + atomic_dec(&mad_agent_priv->refcount); 1902 + 1903 + mad_send_wc.status = IB_WC_SUCCESS; 1904 + mad_send_wc.vendor_err = 0; 1905 + mad_send_wc.send_buf = &mad_send_wr->send_buf; 1906 + ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc); 1890 1907 } 1891 - ib_mark_mad_done(mad_send_wr); 1892 - spin_unlock_irqrestore(&mad_agent_priv->lock, flags); 1893 - 1894 - /* Defined behavior is to complete response before request */ 1895 - mad_recv_wc->wc->wr_id = (unsigned long) &mad_send_wr->send_buf; 1896 - mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, 1897 - mad_recv_wc); 1898 - atomic_dec(&mad_agent_priv->refcount); 1899 - 1900 - mad_send_wc.status = IB_WC_SUCCESS; 1901 - mad_send_wc.vendor_err = 0; 1902 - mad_send_wc.send_buf = &mad_send_wr->send_buf; 1903 - ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc); 1904 1908 } else { 1905 1909 mad_agent_priv->agent.recv_handler(&mad_agent_priv->agent, 1906 1910 mad_recv_wc); ··· 2156 2128 2157 2129 mad_agent_priv = mad_send_wr->mad_agent_priv; 2158 2130 spin_lock_irqsave(&mad_agent_priv->lock, flags); 2159 - if (mad_agent_priv->agent.rmpp_version) { 2131 + if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) { 2160 2132 ret = ib_process_rmpp_send_wc(mad_send_wr, mad_send_wc); 2161 2133 if (ret == IB_RMPP_RESULT_CONSUMED) 2162 2134 goto done; ··· 2552 2524 2553 2525 mad_send_wr->timeout = msecs_to_jiffies(mad_send_wr->send_buf.timeout_ms); 2554 2526 2555 - if (mad_send_wr->mad_agent_priv->agent.rmpp_version) { 2527 + if (ib_mad_kernel_rmpp_agent(&mad_send_wr->mad_agent_priv->agent)) { 2556 2528 ret = ib_retry_rmpp(mad_send_wr); 2557 2529 switch (ret) { 2558 2530 case IB_RMPP_RESULT_UNHANDLED:
+22 -12
drivers/infiniband/core/user_mad.c
··· 506 506 507 507 rmpp_mad = (struct ib_rmpp_mad *) packet->mad.data; 508 508 hdr_len = ib_get_mad_data_offset(rmpp_mad->mad_hdr.mgmt_class); 509 - if (!ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class)) { 510 - copy_offset = IB_MGMT_MAD_HDR; 511 - rmpp_active = 0; 512 - } else { 509 + 510 + if (ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class) 511 + && ib_mad_kernel_rmpp_agent(agent)) { 513 512 copy_offset = IB_MGMT_RMPP_HDR; 514 513 rmpp_active = ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & 515 - IB_MGMT_RMPP_FLAG_ACTIVE; 514 + IB_MGMT_RMPP_FLAG_ACTIVE; 515 + } else { 516 + copy_offset = IB_MGMT_MAD_HDR; 517 + rmpp_active = 0; 516 518 } 517 519 518 520 data_len = count - hdr_size(file) - hdr_len; ··· 560 558 rmpp_mad->mad_hdr.tid = *tid; 561 559 } 562 560 563 - spin_lock_irq(&file->send_lock); 564 - ret = is_duplicate(file, packet); 565 - if (!ret) 561 + if (!ib_mad_kernel_rmpp_agent(agent) 562 + && ib_is_mad_class_rmpp(rmpp_mad->mad_hdr.mgmt_class) 563 + && (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) & IB_MGMT_RMPP_FLAG_ACTIVE)) { 564 + spin_lock_irq(&file->send_lock); 566 565 list_add_tail(&packet->list, &file->send_list); 567 - spin_unlock_irq(&file->send_lock); 568 - if (ret) { 569 - ret = -EINVAL; 570 - goto err_msg; 566 + spin_unlock_irq(&file->send_lock); 567 + } else { 568 + spin_lock_irq(&file->send_lock); 569 + ret = is_duplicate(file, packet); 570 + if (!ret) 571 + list_add_tail(&packet->list, &file->send_list); 572 + spin_unlock_irq(&file->send_lock); 573 + if (ret) { 574 + ret = -EINVAL; 575 + goto err_msg; 576 + } 571 577 } 572 578 573 579 ret = ib_post_send_mad(packet->msg, NULL);
+11
include/rdma/ib_mad.h
··· 40 40 #include <linux/list.h> 41 41 42 42 #include <rdma/ib_verbs.h> 43 + #include <uapi/rdma/ib_user_mad.h> 43 44 44 45 /* Management base version */ 45 46 #define IB_MGMT_BASE_VERSION 1 ··· 360 359 * @port_num: Port number on which QP is registered 361 360 * @rmpp_version: If set, indicates the RMPP version used by this agent. 362 361 */ 362 + enum { 363 + IB_MAD_USER_RMPP = IB_USER_MAD_USER_RMPP, 364 + }; 363 365 struct ib_mad_agent { 364 366 struct ib_device *device; 365 367 struct ib_qp *qp; ··· 669 665 * @send_buf: Previously allocated send data buffer. 670 666 */ 671 667 void ib_free_send_mad(struct ib_mad_send_buf *send_buf); 668 + 669 + /** 670 + * ib_mad_kernel_rmpp_agent - Returns if the agent is performing RMPP. 671 + * @agent: the agent in question 672 + * @return: true if agent is performing rmpp, false otherwise. 673 + */ 674 + int ib_mad_kernel_rmpp_agent(struct ib_mad_agent *agent); 672 675 673 676 #endif /* IB_MAD_H */
+4 -1
include/uapi/rdma/ib_user_mad.h
··· 213 213 * used. 214 214 * @rmpp_version - If set, indicates the RMPP version to use. 215 215 */ 216 - #define IB_USER_MAD_REG_FLAGS_CAP (0) 216 + enum { 217 + IB_USER_MAD_USER_RMPP = (1 << 0), 218 + }; 219 + #define IB_USER_MAD_REG_FLAGS_CAP (IB_USER_MAD_USER_RMPP) 217 220 struct ib_user_mad_reg_req2 { 218 221 __u32 id; 219 222 __u32 qpn;