2 * Copyright (c) 2007 Cisco Systems, Inc. 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
34 #include <rdma/ib_addr.h>
35 #include <linux/inet.h>
36 #include <linux/string.h>
37 #include <rdma/ib_cache.h>
39 int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
40 u8 *mac, int *is_mcast, u8 port)
42 struct mlx4_ib_iboe *iboe = &dev->iboe;
46 spin_lock(&iboe->lock);
47 if (!iboe->netdevs[port - 1]) {
48 spin_unlock(&iboe->lock);
51 spin_unlock(&iboe->lock);
53 memcpy(&in6, ah_attr->grh.dgid.raw, sizeof in6);
54 if (rdma_link_local_addr(&in6))
55 rdma_get_ll_mac(&in6, mac);
56 else if (rdma_is_multicast_addr(&in6)) {
57 rdma_get_mcast_mac(&in6, mac);
65 static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
66 struct mlx4_ib_ah *ah)
68 struct mlx4_dev *dev = to_mdev(pd->device)->dev;
70 ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
71 ah->av.ib.g_slid = ah_attr->src_path_bits;
72 if (ah_attr->ah_flags & IB_AH_GRH) {
73 ah->av.ib.g_slid |= 0x80;
74 ah->av.ib.gid_index = ah_attr->grh.sgid_index;
75 ah->av.ib.hop_limit = ah_attr->grh.hop_limit;
76 ah->av.ib.sl_tclass_flowlabel |=
77 cpu_to_be32((ah_attr->grh.traffic_class << 20) |
78 ah_attr->grh.flow_label);
79 memcpy(ah->av.ib.dgid, ah_attr->grh.dgid.raw, 16);
82 ah->av.ib.dlid = cpu_to_be16(ah_attr->dlid);
83 if (ah_attr->static_rate) {
84 ah->av.ib.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
85 while (ah->av.ib.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
86 !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
87 --ah->av.ib.stat_rate;
89 ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
94 static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
95 struct mlx4_ib_ah *ah)
97 struct mlx4_ib_dev *ibdev = to_mdev(pd->device);
98 struct mlx4_dev *dev = ibdev->dev;
105 err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num);
109 memcpy(ah->av.eth.mac, mac, 6);
110 err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid);
113 vlan_tag = rdma_get_vlan_id(&sgid);
114 if (vlan_tag < 0x1000)
115 vlan_tag |= (ah_attr->sl & 7) << 13;
116 ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
117 ah->av.eth.gid_index = ah_attr->grh.sgid_index;
118 ah->av.eth.vlan = cpu_to_be16(vlan_tag);
119 if (ah_attr->static_rate) {
120 ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
121 while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
122 !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
123 --ah->av.eth.stat_rate;
127 * HW requires multicast LID so we just choose one.
130 ah->av.ib.dlid = cpu_to_be16(0xc000);
132 memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16);
133 ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
138 struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
140 struct mlx4_ib_ah *ah;
143 ah = kzalloc(sizeof *ah, GFP_ATOMIC);
145 return ERR_PTR(-ENOMEM);
147 if (rdma_port_get_link_layer(pd->device, ah_attr->port_num) == IB_LINK_LAYER_ETHERNET) {
148 if (!(ah_attr->ah_flags & IB_AH_GRH)) {
149 ret = ERR_PTR(-EINVAL);
152 /* TBD: need to handle the case when we get called
153 in an atomic context and there we might sleep. We
154 don't expect this currently since we're working with
155 link local addresses which we can translate without
157 ret = create_iboe_ah(pd, ah_attr, ah);
164 return create_ib_ah(pd, ah_attr, ah); /* never fails */
171 int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
173 struct mlx4_ib_ah *ah = to_mah(ibah);
174 enum rdma_link_layer ll;
176 memset(ah_attr, 0, sizeof *ah_attr);
177 ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
178 ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
179 ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
180 ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
181 if (ah->av.ib.stat_rate)
182 ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
183 ah_attr->src_path_bits = ah->av.ib.g_slid & 0x7F;
185 if (mlx4_ib_ah_grh_present(ah)) {
186 ah_attr->ah_flags = IB_AH_GRH;
188 ah_attr->grh.traffic_class =
189 be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 20;
190 ah_attr->grh.flow_label =
191 be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) & 0xfffff;
192 ah_attr->grh.hop_limit = ah->av.ib.hop_limit;
193 ah_attr->grh.sgid_index = ah->av.ib.gid_index;
194 memcpy(ah_attr->grh.dgid.raw, ah->av.ib.dgid, 16);
200 int mlx4_ib_destroy_ah(struct ib_ah *ah)