]>
Commit | Line | Data |
---|---|---|
9a443537 | 1 | /* |
2 | * Copyright (c) 2016 Hisilicon Limited. | |
3 | * | |
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: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or | |
11 | * without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistributions of source code must retain the above | |
15 | * copyright notice, this list of conditions and the following | |
16 | * disclaimer. | |
17 | * | |
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. | |
22 | * | |
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 | |
30 | * SOFTWARE. | |
31 | */ | |
32 | ||
33 | #include <linux/platform_device.h> | |
34 | #include <rdma/ib_addr.h> | |
35 | #include <rdma/ib_cache.h> | |
36 | #include "hns_roce_device.h" | |
37 | ||
38 | #define HNS_ROCE_PORT_NUM_SHIFT 24 | |
39 | #define HNS_ROCE_VLAN_SL_BIT_MASK 7 | |
40 | #define HNS_ROCE_VLAN_SL_SHIFT 13 | |
41 | ||
90898850 DC |
42 | struct ib_ah *hns_roce_create_ah(struct ib_pd *ibpd, |
43 | struct rdma_ah_attr *ah_attr, | |
477864c8 | 44 | struct ib_udata *udata) |
9a443537 | 45 | { |
46 | struct hns_roce_dev *hr_dev = to_hr_dev(ibpd->device); | |
47 | struct device *dev = &hr_dev->pdev->dev; | |
48 | struct ib_gid_attr gid_attr; | |
49 | struct hns_roce_ah *ah; | |
50 | u16 vlan_tag = 0xffff; | |
51 | struct in6_addr in6; | |
d8966fcd | 52 | const struct ib_global_route *grh = rdma_ah_read_grh(ah_attr); |
9a443537 | 53 | union ib_gid sgid; |
54 | int ret; | |
55 | ||
56 | ah = kzalloc(sizeof(*ah), GFP_ATOMIC); | |
57 | if (!ah) | |
58 | return ERR_PTR(-ENOMEM); | |
59 | ||
60 | /* Get mac address */ | |
d8966fcd DC |
61 | memcpy(&in6, grh->dgid.raw, sizeof(grh->dgid.raw)); |
62 | if (rdma_is_multicast_addr(&in6)) { | |
9a443537 | 63 | rdma_get_mcast_mac(&in6, ah->av.mac); |
d8966fcd DC |
64 | } else { |
65 | u8 *dmac = rdma_ah_retrieve_dmac(ah_attr); | |
66 | ||
5b59a396 CIK |
67 | if (!dmac) { |
68 | kfree(ah); | |
d8966fcd | 69 | return ERR_PTR(-EINVAL); |
5b59a396 | 70 | } |
d8966fcd DC |
71 | memcpy(ah->av.mac, dmac, ETH_ALEN); |
72 | } | |
9a443537 | 73 | |
74 | /* Get source gid */ | |
d8966fcd DC |
75 | ret = ib_get_cached_gid(ibpd->device, rdma_ah_get_port_num(ah_attr), |
76 | grh->sgid_index, &sgid, &gid_attr); | |
9a443537 | 77 | if (ret) { |
78 | dev_err(dev, "get sgid failed! ret = %d\n", ret); | |
79 | kfree(ah); | |
80 | return ERR_PTR(ret); | |
81 | } | |
82 | ||
83 | if (gid_attr.ndev) { | |
84 | if (is_vlan_dev(gid_attr.ndev)) | |
85 | vlan_tag = vlan_dev_vlan_id(gid_attr.ndev); | |
86 | dev_put(gid_attr.ndev); | |
87 | } | |
88 | ||
89 | if (vlan_tag < 0x1000) | |
d8966fcd DC |
90 | vlan_tag |= (rdma_ah_get_sl(ah_attr) & |
91 | HNS_ROCE_VLAN_SL_BIT_MASK) << | |
9a443537 | 92 | HNS_ROCE_VLAN_SL_SHIFT; |
93 | ||
d8966fcd DC |
94 | ah->av.port_pd = cpu_to_be32(to_hr_pd(ibpd)->pdn | |
95 | (rdma_ah_get_port_num(ah_attr) << | |
9a443537 | 96 | HNS_ROCE_PORT_NUM_SHIFT)); |
d8966fcd | 97 | ah->av.gid_index = grh->sgid_index; |
9a443537 | 98 | ah->av.vlan = cpu_to_le16(vlan_tag); |
99 | dev_dbg(dev, "gid_index = 0x%x,vlan = 0x%x\n", ah->av.gid_index, | |
100 | ah->av.vlan); | |
101 | ||
d8966fcd | 102 | if (rdma_ah_get_static_rate(ah_attr)) |
9a443537 | 103 | ah->av.stat_rate = IB_RATE_10_GBPS; |
104 | ||
d8966fcd DC |
105 | memcpy(ah->av.dgid, grh->dgid.raw, HNS_ROCE_GID_SIZE); |
106 | ah->av.sl_tclass_flowlabel = cpu_to_le32(rdma_ah_get_sl(ah_attr) << | |
9a443537 | 107 | HNS_ROCE_SL_SHIFT); |
108 | ||
109 | return &ah->ibah; | |
110 | } | |
111 | ||
90898850 | 112 | int hns_roce_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr) |
9a443537 | 113 | { |
114 | struct hns_roce_ah *ah = to_hr_ah(ibah); | |
115 | ||
116 | memset(ah_attr, 0, sizeof(*ah_attr)); | |
117 | ||
d8966fcd DC |
118 | rdma_ah_set_sl(ah_attr, (le32_to_cpu(ah->av.sl_tclass_flowlabel) >> |
119 | HNS_ROCE_SL_SHIFT)); | |
120 | rdma_ah_set_port_num(ah_attr, (le32_to_cpu(ah->av.port_pd) >> | |
121 | HNS_ROCE_PORT_NUM_SHIFT)); | |
122 | rdma_ah_set_static_rate(ah_attr, ah->av.stat_rate); | |
123 | rdma_ah_set_grh(ah_attr, NULL, | |
124 | (le32_to_cpu(ah->av.sl_tclass_flowlabel) & | |
125 | HNS_ROCE_FLOW_LABLE_MASK), ah->av.gid_index, | |
126 | ah->av.hop_limit, | |
127 | (le32_to_cpu(ah->av.sl_tclass_flowlabel) >> | |
128 | HNS_ROCE_TCLASS_SHIFT)); | |
129 | rdma_ah_set_dgid_raw(ah_attr, ah->av.dgid); | |
9a443537 | 130 | |
131 | return 0; | |
132 | } | |
133 | ||
134 | int hns_roce_destroy_ah(struct ib_ah *ah) | |
135 | { | |
136 | kfree(to_hr_ah(ah)); | |
137 | ||
138 | return 0; | |
139 | } |