18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 58c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 118c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 128c2ecf20Sopenharmony_ci * conditions are met: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 158c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 168c2ecf20Sopenharmony_ci * disclaimer. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 198c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 208c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 218c2ecf20Sopenharmony_ci * provided with the distribution. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 308c2ecf20Sopenharmony_ci * SOFTWARE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "mlx5_ib.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic __be16 mlx5_ah_get_udp_sport(const struct mlx5_ib_dev *dev, 368c2ecf20Sopenharmony_ci const struct rdma_ah_attr *ah_attr) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci enum ib_gid_type gid_type = ah_attr->grh.sgid_attr->gid_type; 398c2ecf20Sopenharmony_ci __be16 sport; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if ((gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) && 428c2ecf20Sopenharmony_ci (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) && 438c2ecf20Sopenharmony_ci (ah_attr->grh.flow_label & IB_GRH_FLOWLABEL_MASK)) 448c2ecf20Sopenharmony_ci sport = cpu_to_be16( 458c2ecf20Sopenharmony_ci rdma_flow_label_to_udp_sport(ah_attr->grh.flow_label)); 468c2ecf20Sopenharmony_ci else 478c2ecf20Sopenharmony_ci sport = mlx5_get_roce_udp_sport_min(dev, 488c2ecf20Sopenharmony_ci ah_attr->grh.sgid_attr); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci return sport; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic void create_ib_ah(struct mlx5_ib_dev *dev, struct mlx5_ib_ah *ah, 548c2ecf20Sopenharmony_ci struct rdma_ah_init_attr *init_attr) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct rdma_ah_attr *ah_attr = init_attr->ah_attr; 578c2ecf20Sopenharmony_ci enum ib_gid_type gid_type; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci if (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) { 608c2ecf20Sopenharmony_ci const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci memcpy(ah->av.rgid, &grh->dgid, 16); 638c2ecf20Sopenharmony_ci ah->av.grh_gid_fl = cpu_to_be32(grh->flow_label | 648c2ecf20Sopenharmony_ci (1 << 30) | 658c2ecf20Sopenharmony_ci grh->sgid_index << 20); 668c2ecf20Sopenharmony_ci ah->av.hop_limit = grh->hop_limit; 678c2ecf20Sopenharmony_ci ah->av.tclass = grh->traffic_class; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci ah->av.stat_rate_sl = (rdma_ah_get_static_rate(ah_attr) << 4); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) { 738c2ecf20Sopenharmony_ci if (init_attr->xmit_slave) 748c2ecf20Sopenharmony_ci ah->xmit_port = 758c2ecf20Sopenharmony_ci mlx5_lag_get_slave_port(dev->mdev, 768c2ecf20Sopenharmony_ci init_attr->xmit_slave); 778c2ecf20Sopenharmony_ci gid_type = ah_attr->grh.sgid_attr->gid_type; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci memcpy(ah->av.rmac, ah_attr->roce.dmac, 808c2ecf20Sopenharmony_ci sizeof(ah_attr->roce.dmac)); 818c2ecf20Sopenharmony_ci ah->av.udp_sport = mlx5_ah_get_udp_sport(dev, ah_attr); 828c2ecf20Sopenharmony_ci ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0x7) << 1; 838c2ecf20Sopenharmony_ci if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) 848c2ecf20Sopenharmony_ci#define MLX5_ECN_ENABLED BIT(1) 858c2ecf20Sopenharmony_ci ah->av.tclass |= MLX5_ECN_ENABLED; 868c2ecf20Sopenharmony_ci } else { 878c2ecf20Sopenharmony_ci ah->av.rlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr)); 888c2ecf20Sopenharmony_ci ah->av.fl_mlid = rdma_ah_get_path_bits(ah_attr) & 0x7f; 898c2ecf20Sopenharmony_ci ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0xf); 908c2ecf20Sopenharmony_ci } 918c2ecf20Sopenharmony_ci} 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ciint mlx5_ib_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr, 948c2ecf20Sopenharmony_ci struct ib_udata *udata) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct rdma_ah_attr *ah_attr = init_attr->ah_attr; 988c2ecf20Sopenharmony_ci struct mlx5_ib_ah *ah = to_mah(ibah); 998c2ecf20Sopenharmony_ci struct mlx5_ib_dev *dev = to_mdev(ibah->device); 1008c2ecf20Sopenharmony_ci enum rdma_ah_attr_type ah_type = ah_attr->type; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci if ((ah_type == RDMA_AH_ATTR_TYPE_ROCE) && 1038c2ecf20Sopenharmony_ci !(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH)) 1048c2ecf20Sopenharmony_ci return -EINVAL; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci if (ah_type == RDMA_AH_ATTR_TYPE_ROCE && udata) { 1078c2ecf20Sopenharmony_ci int err; 1088c2ecf20Sopenharmony_ci struct mlx5_ib_create_ah_resp resp = {}; 1098c2ecf20Sopenharmony_ci u32 min_resp_len = 1108c2ecf20Sopenharmony_ci offsetofend(struct mlx5_ib_create_ah_resp, dmac); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci if (udata->outlen < min_resp_len) 1138c2ecf20Sopenharmony_ci return -EINVAL; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci resp.response_length = min_resp_len; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci memcpy(resp.dmac, ah_attr->roce.dmac, ETH_ALEN); 1188c2ecf20Sopenharmony_ci err = ib_copy_to_udata(udata, &resp, resp.response_length); 1198c2ecf20Sopenharmony_ci if (err) 1208c2ecf20Sopenharmony_ci return err; 1218c2ecf20Sopenharmony_ci } 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci create_ib_ah(dev, ah, init_attr); 1248c2ecf20Sopenharmony_ci return 0; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ciint mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci struct mlx5_ib_ah *ah = to_mah(ibah); 1308c2ecf20Sopenharmony_ci u32 tmp; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci memset(ah_attr, 0, sizeof(*ah_attr)); 1338c2ecf20Sopenharmony_ci ah_attr->type = ibah->type; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci tmp = be32_to_cpu(ah->av.grh_gid_fl); 1368c2ecf20Sopenharmony_ci if (tmp & (1 << 30)) { 1378c2ecf20Sopenharmony_ci rdma_ah_set_grh(ah_attr, NULL, 1388c2ecf20Sopenharmony_ci tmp & 0xfffff, 1398c2ecf20Sopenharmony_ci (tmp >> 20) & 0xff, 1408c2ecf20Sopenharmony_ci ah->av.hop_limit, 1418c2ecf20Sopenharmony_ci ah->av.tclass); 1428c2ecf20Sopenharmony_ci rdma_ah_set_dgid_raw(ah_attr, ah->av.rgid); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci rdma_ah_set_dlid(ah_attr, be16_to_cpu(ah->av.rlid)); 1458c2ecf20Sopenharmony_ci rdma_ah_set_static_rate(ah_attr, ah->av.stat_rate_sl >> 4); 1468c2ecf20Sopenharmony_ci rdma_ah_set_sl(ah_attr, ah->av.stat_rate_sl & 0xf); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 150