0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033 #include "mlx5_ib.h"
0034
0035 static __be16 mlx5_ah_get_udp_sport(const struct mlx5_ib_dev *dev,
0036 const struct rdma_ah_attr *ah_attr)
0037 {
0038 enum ib_gid_type gid_type = ah_attr->grh.sgid_attr->gid_type;
0039 __be16 sport;
0040
0041 if ((gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP) &&
0042 (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) &&
0043 (ah_attr->grh.flow_label & IB_GRH_FLOWLABEL_MASK))
0044 sport = cpu_to_be16(
0045 rdma_flow_label_to_udp_sport(ah_attr->grh.flow_label));
0046 else
0047 sport = mlx5_get_roce_udp_sport_min(dev,
0048 ah_attr->grh.sgid_attr);
0049
0050 return sport;
0051 }
0052
0053 static void create_ib_ah(struct mlx5_ib_dev *dev, struct mlx5_ib_ah *ah,
0054 struct rdma_ah_init_attr *init_attr)
0055 {
0056 struct rdma_ah_attr *ah_attr = init_attr->ah_attr;
0057 enum ib_gid_type gid_type;
0058
0059 if (rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH) {
0060 const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr);
0061
0062 memcpy(ah->av.rgid, &grh->dgid, 16);
0063 ah->av.grh_gid_fl = cpu_to_be32(grh->flow_label |
0064 (1 << 30) |
0065 grh->sgid_index << 20);
0066 ah->av.hop_limit = grh->hop_limit;
0067 ah->av.tclass = grh->traffic_class;
0068 }
0069
0070 ah->av.stat_rate_sl = (rdma_ah_get_static_rate(ah_attr) << 4);
0071
0072 if (ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
0073 if (init_attr->xmit_slave)
0074 ah->xmit_port =
0075 mlx5_lag_get_slave_port(dev->mdev,
0076 init_attr->xmit_slave);
0077 gid_type = ah_attr->grh.sgid_attr->gid_type;
0078
0079 memcpy(ah->av.rmac, ah_attr->roce.dmac,
0080 sizeof(ah_attr->roce.dmac));
0081 ah->av.udp_sport = mlx5_ah_get_udp_sport(dev, ah_attr);
0082 ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0x7) << 1;
0083 if (gid_type == IB_GID_TYPE_ROCE_UDP_ENCAP)
0084 #define MLX5_ECN_ENABLED BIT(1)
0085 ah->av.tclass |= MLX5_ECN_ENABLED;
0086 } else {
0087 ah->av.rlid = cpu_to_be16(rdma_ah_get_dlid(ah_attr));
0088 ah->av.fl_mlid = rdma_ah_get_path_bits(ah_attr) & 0x7f;
0089 ah->av.stat_rate_sl |= (rdma_ah_get_sl(ah_attr) & 0xf);
0090 }
0091 }
0092
0093 int mlx5_ib_create_ah(struct ib_ah *ibah, struct rdma_ah_init_attr *init_attr,
0094 struct ib_udata *udata)
0095
0096 {
0097 struct rdma_ah_attr *ah_attr = init_attr->ah_attr;
0098 struct mlx5_ib_ah *ah = to_mah(ibah);
0099 struct mlx5_ib_dev *dev = to_mdev(ibah->device);
0100 enum rdma_ah_attr_type ah_type = ah_attr->type;
0101
0102 if ((ah_type == RDMA_AH_ATTR_TYPE_ROCE) &&
0103 !(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
0104 return -EINVAL;
0105
0106 if (ah_type == RDMA_AH_ATTR_TYPE_ROCE && udata) {
0107 int err;
0108 struct mlx5_ib_create_ah_resp resp = {};
0109 u32 min_resp_len =
0110 offsetofend(struct mlx5_ib_create_ah_resp, dmac);
0111
0112 if (udata->outlen < min_resp_len)
0113 return -EINVAL;
0114
0115 resp.response_length = min_resp_len;
0116
0117 memcpy(resp.dmac, ah_attr->roce.dmac, ETH_ALEN);
0118 err = ib_copy_to_udata(udata, &resp, resp.response_length);
0119 if (err)
0120 return err;
0121 }
0122
0123 create_ib_ah(dev, ah, init_attr);
0124 return 0;
0125 }
0126
0127 int mlx5_ib_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr)
0128 {
0129 struct mlx5_ib_ah *ah = to_mah(ibah);
0130 u32 tmp;
0131
0132 memset(ah_attr, 0, sizeof(*ah_attr));
0133 ah_attr->type = ibah->type;
0134
0135 tmp = be32_to_cpu(ah->av.grh_gid_fl);
0136 if (tmp & (1 << 30)) {
0137 rdma_ah_set_grh(ah_attr, NULL,
0138 tmp & 0xfffff,
0139 (tmp >> 20) & 0xff,
0140 ah->av.hop_limit,
0141 ah->av.tclass);
0142 rdma_ah_set_dgid_raw(ah_attr, ah->av.rgid);
0143 }
0144 rdma_ah_set_dlid(ah_attr, be16_to_cpu(ah->av.rlid));
0145 rdma_ah_set_static_rate(ah_attr, ah->av.stat_rate_sl >> 4);
0146 rdma_ah_set_sl(ah_attr, ah->av.stat_rate_sl & 0xf);
0147
0148 return 0;
0149 }