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

IB/mad: Add partial Intel OPA MAD support

This patch is the first of 3 which adds processing of OPA MADs

1) Add Intel Omni-Path Architecture defines
2) Increase max management version to accommodate OPA
3) update ib_create_send_mad
If the device supports OPA MADs and the MAD being sent is the OPA base
version alter the MAD size and sg lengths as appropriate

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>

authored by

Ira Weiny and committed by
Doug Ledford
548ead17 65995fee

+58 -17
+32 -10
drivers/infiniband/core/mad.c
··· 874 874 return ret; 875 875 } 876 876 877 - static int get_pad_size(int hdr_len, int data_len) 877 + static int get_pad_size(int hdr_len, int data_len, size_t mad_size) 878 878 { 879 879 int seg_size, pad; 880 880 881 - seg_size = sizeof(struct ib_mad) - hdr_len; 881 + seg_size = mad_size - hdr_len; 882 882 if (data_len && seg_size) { 883 883 pad = seg_size - data_len % seg_size; 884 884 return pad == seg_size ? 0 : pad; ··· 897 897 } 898 898 899 899 static int alloc_send_rmpp_list(struct ib_mad_send_wr_private *send_wr, 900 - gfp_t gfp_mask) 900 + size_t mad_size, gfp_t gfp_mask) 901 901 { 902 902 struct ib_mad_send_buf *send_buf = &send_wr->send_buf; 903 903 struct ib_rmpp_mad *rmpp_mad = send_buf->mad; 904 904 struct ib_rmpp_segment *seg = NULL; 905 905 int left, seg_size, pad; 906 906 907 - send_buf->seg_size = sizeof(struct ib_mad) - send_buf->hdr_len; 907 + send_buf->seg_size = mad_size - send_buf->hdr_len; 908 + send_buf->seg_rmpp_size = mad_size - IB_MGMT_RMPP_HDR; 908 909 seg_size = send_buf->seg_size; 909 910 pad = send_wr->pad; 910 911 ··· 955 954 struct ib_mad_send_wr_private *mad_send_wr; 956 955 int pad, message_size, ret, size; 957 956 void *buf; 957 + size_t mad_size; 958 + bool opa; 958 959 959 960 mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private, 960 961 agent); 961 - pad = get_pad_size(hdr_len, data_len); 962 + 963 + opa = rdma_cap_opa_mad(mad_agent->device, mad_agent->port_num); 964 + 965 + if (opa && base_version == OPA_MGMT_BASE_VERSION) 966 + mad_size = sizeof(struct opa_mad); 967 + else 968 + mad_size = sizeof(struct ib_mad); 969 + 970 + pad = get_pad_size(hdr_len, data_len, mad_size); 962 971 message_size = hdr_len + data_len + pad; 963 972 964 973 if (ib_mad_kernel_rmpp_agent(mad_agent)) { 965 - if (!rmpp_active && message_size > sizeof(struct ib_mad)) 974 + if (!rmpp_active && message_size > mad_size) 966 975 return ERR_PTR(-EINVAL); 967 976 } else 968 - if (rmpp_active || message_size > sizeof(struct ib_mad)) 977 + if (rmpp_active || message_size > mad_size) 969 978 return ERR_PTR(-EINVAL); 970 979 971 - size = rmpp_active ? hdr_len : sizeof(struct ib_mad); 980 + size = rmpp_active ? hdr_len : mad_size; 972 981 buf = kzalloc(sizeof *mad_send_wr + size, gfp_mask); 973 982 if (!buf) 974 983 return ERR_PTR(-ENOMEM); ··· 993 982 mad_send_wr->mad_agent_priv = mad_agent_priv; 994 983 mad_send_wr->sg_list[0].length = hdr_len; 995 984 mad_send_wr->sg_list[0].lkey = mad_agent->mr->lkey; 996 - mad_send_wr->sg_list[1].length = sizeof(struct ib_mad) - hdr_len; 985 + 986 + /* OPA MADs don't have to be the full 2048 bytes */ 987 + if (opa && base_version == OPA_MGMT_BASE_VERSION && 988 + data_len < mad_size - hdr_len) 989 + mad_send_wr->sg_list[1].length = data_len; 990 + else 991 + mad_send_wr->sg_list[1].length = mad_size - hdr_len; 992 + 997 993 mad_send_wr->sg_list[1].lkey = mad_agent->mr->lkey; 998 994 999 995 mad_send_wr->send_wr.wr_id = (unsigned long) mad_send_wr; ··· 1013 995 mad_send_wr->send_wr.wr.ud.pkey_index = pkey_index; 1014 996 1015 997 if (rmpp_active) { 1016 - ret = alloc_send_rmpp_list(mad_send_wr, gfp_mask); 998 + ret = alloc_send_rmpp_list(mad_send_wr, mad_size, gfp_mask); 1017 999 if (ret) { 1018 1000 kfree(buf); 1019 1001 return ERR_PTR(ret); ··· 2992 2974 struct ib_cq_init_attr cq_attr = {}; 2993 2975 2994 2976 if (WARN_ON(rdma_max_mad_size(device, port_num) < IB_MGMT_MAD_SIZE)) 2977 + return -EFAULT; 2978 + 2979 + if (WARN_ON(rdma_cap_opa_mad(device, port_num) && 2980 + rdma_max_mad_size(device, port_num) < OPA_MGMT_MAD_SIZE)) 2995 2981 return -EFAULT; 2996 2982 2997 2983 /* Create new device info */
+1 -1
drivers/infiniband/core/mad_priv.h
··· 56 56 57 57 /* Registration table sizes */ 58 58 #define MAX_MGMT_CLASS 80 59 - #define MAX_MGMT_VERSION 8 59 + #define MAX_MGMT_VERSION 0x83 60 60 #define MAX_MGMT_OUI 8 61 61 #define MAX_MGMT_VENDOR_RANGE2 (IB_MGMT_CLASS_VENDOR_RANGE2_END - \ 62 62 IB_MGMT_CLASS_VENDOR_RANGE2_START + 1)
+4 -3
drivers/infiniband/core/mad_rmpp.c
··· 572 572 573 573 if (mad_send_wr->seg_num == 1) { 574 574 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_FIRST; 575 - paylen = mad_send_wr->send_buf.seg_count * IB_MGMT_RMPP_DATA - 576 - mad_send_wr->pad; 575 + paylen = (mad_send_wr->send_buf.seg_count * 576 + mad_send_wr->send_buf.seg_rmpp_size) - 577 + mad_send_wr->pad; 577 578 } 578 579 579 580 if (mad_send_wr->seg_num == mad_send_wr->send_buf.seg_count) { 580 581 rmpp_mad->rmpp_hdr.rmpp_rtime_flags |= IB_MGMT_RMPP_FLAG_LAST; 581 - paylen = IB_MGMT_RMPP_DATA - mad_send_wr->pad; 582 + paylen = mad_send_wr->send_buf.seg_rmpp_size - mad_send_wr->pad; 582 583 } 583 584 rmpp_mad->rmpp_hdr.paylen_newwin = cpu_to_be32(paylen); 584 585
+21 -3
include/rdma/ib_mad.h
··· 42 42 #include <rdma/ib_verbs.h> 43 43 #include <uapi/rdma/ib_user_mad.h> 44 44 45 - /* Management base version */ 45 + /* Management base versions */ 46 46 #define IB_MGMT_BASE_VERSION 1 47 + #define OPA_MGMT_BASE_VERSION 0x80 48 + 49 + #define OPA_SMP_CLASS_VERSION 0x80 47 50 48 51 /* Management classes */ 49 52 #define IB_MGMT_CLASS_SUBN_LID_ROUTED 0x01 ··· 139 136 IB_MGMT_DEVICE_HDR = 64, 140 137 IB_MGMT_DEVICE_DATA = 192, 141 138 IB_MGMT_MAD_SIZE = IB_MGMT_MAD_HDR + IB_MGMT_MAD_DATA, 139 + OPA_MGMT_MAD_DATA = 2024, 140 + OPA_MGMT_RMPP_DATA = 2012, 141 + OPA_MGMT_MAD_SIZE = IB_MGMT_MAD_HDR + OPA_MGMT_MAD_DATA, 142 142 }; 143 143 144 144 struct ib_mad_hdr { ··· 186 180 struct ib_mad { 187 181 struct ib_mad_hdr mad_hdr; 188 182 u8 data[IB_MGMT_MAD_DATA]; 183 + }; 184 + 185 + struct opa_mad { 186 + struct ib_mad_hdr mad_hdr; 187 + u8 data[OPA_MGMT_MAD_DATA]; 189 188 }; 190 189 191 190 struct ib_rmpp_mad { ··· 247 236 * includes the common MAD, RMPP, and class specific headers. 248 237 * @data_len: Indicates the total size of user-transferred data. 249 238 * @seg_count: The number of RMPP segments allocated for this send. 250 - * @seg_size: Size of each RMPP segment. 239 + * @seg_size: Size of the data in each RMPP segment. This does not include 240 + * class specific headers. 241 + * @seg_rmpp_size: Size of each RMPP segment including the class specific 242 + * headers. 251 243 * @timeout_ms: Time to wait for a response. 252 244 * @retries: Number of times to retry a request for a response. For MADs 253 245 * using RMPP, this applies per window. On completion, returns the number ··· 270 256 int data_len; 271 257 int seg_count; 272 258 int seg_size; 259 + int seg_rmpp_size; 273 260 int timeout_ms; 274 261 int retries; 275 262 }; ··· 417 402 struct ib_mad_recv_buf { 418 403 struct list_head list; 419 404 struct ib_grh *grh; 420 - struct ib_mad *mad; 405 + union { 406 + struct ib_mad *mad; 407 + struct opa_mad *opa_mad; 408 + }; 421 409 }; 422 410 423 411 /**