2 * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 static struct ib_ah
*create_ib_ah(struct mlx5_ib_dev
*dev
,
36 struct mlx5_ib_ah
*ah
,
37 struct rdma_ah_attr
*ah_attr
)
39 if (rdma_ah_get_ah_flags(ah_attr
) & IB_AH_GRH
) {
40 const struct ib_global_route
*grh
= rdma_ah_read_grh(ah_attr
);
42 memcpy(ah
->av
.rgid
, &grh
->dgid
, 16);
43 ah
->av
.grh_gid_fl
= cpu_to_be32(grh
->flow_label
|
45 grh
->sgid_index
<< 20);
46 ah
->av
.hop_limit
= grh
->hop_limit
;
47 ah
->av
.tclass
= grh
->traffic_class
;
50 ah
->av
.stat_rate_sl
= (rdma_ah_get_static_rate(ah_attr
) << 4);
52 if (ah_attr
->type
== RDMA_AH_ATTR_TYPE_ROCE
) {
53 memcpy(ah
->av
.rmac
, ah_attr
->roce
.dmac
,
54 sizeof(ah_attr
->roce
.dmac
));
56 mlx5_get_roce_udp_sport(dev
,
57 rdma_ah_get_port_num(ah_attr
),
58 rdma_ah_read_grh(ah_attr
)->sgid_index
);
59 ah
->av
.stat_rate_sl
|= (rdma_ah_get_sl(ah_attr
) & 0x7) << 1;
61 ah
->av
.rlid
= cpu_to_be16(rdma_ah_get_dlid(ah_attr
));
62 ah
->av
.fl_mlid
= rdma_ah_get_path_bits(ah_attr
) & 0x7f;
63 ah
->av
.stat_rate_sl
|= (rdma_ah_get_sl(ah_attr
) & 0xf);
69 struct ib_ah
*mlx5_ib_create_ah(struct ib_pd
*pd
, struct rdma_ah_attr
*ah_attr
,
70 struct ib_udata
*udata
)
73 struct mlx5_ib_ah
*ah
;
74 struct mlx5_ib_dev
*dev
= to_mdev(pd
->device
);
75 enum rdma_ah_attr_type ah_type
= ah_attr
->type
;
77 if ((ah_type
== RDMA_AH_ATTR_TYPE_ROCE
) &&
78 !(rdma_ah_get_ah_flags(ah_attr
) & IB_AH_GRH
))
79 return ERR_PTR(-EINVAL
);
81 if (ah_type
== RDMA_AH_ATTR_TYPE_ROCE
&& udata
) {
83 struct mlx5_ib_create_ah_resp resp
= {};
84 u32 min_resp_len
= offsetof(typeof(resp
), dmac
) +
87 if (udata
->outlen
< min_resp_len
)
88 return ERR_PTR(-EINVAL
);
90 resp
.response_length
= min_resp_len
;
92 memcpy(resp
.dmac
, ah_attr
->roce
.dmac
, ETH_ALEN
);
93 err
= ib_copy_to_udata(udata
, &resp
, resp
.response_length
);
98 ah
= kzalloc(sizeof(*ah
), GFP_ATOMIC
);
100 return ERR_PTR(-ENOMEM
);
102 return create_ib_ah(dev
, ah
, ah_attr
); /* never fails */
105 int mlx5_ib_query_ah(struct ib_ah
*ibah
, struct rdma_ah_attr
*ah_attr
)
107 struct mlx5_ib_ah
*ah
= to_mah(ibah
);
110 memset(ah_attr
, 0, sizeof(*ah_attr
));
111 ah_attr
->type
= ibah
->type
;
113 tmp
= be32_to_cpu(ah
->av
.grh_gid_fl
);
114 if (tmp
& (1 << 30)) {
115 rdma_ah_set_grh(ah_attr
, NULL
,
120 rdma_ah_set_dgid_raw(ah_attr
, ah
->av
.rgid
);
122 rdma_ah_set_dlid(ah_attr
, be16_to_cpu(ah
->av
.rlid
));
123 rdma_ah_set_static_rate(ah_attr
, ah
->av
.stat_rate_sl
>> 4);
124 rdma_ah_set_sl(ah_attr
, ah
->av
.stat_rate_sl
& 0xf);
129 int mlx5_ib_destroy_ah(struct ib_ah
*ah
)