1 /*-
2 * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3 *
4 * Copyright (c) 2016 - 2021 Intel Corporation
5 *
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenFabrics.org BSD license below:
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer.
19 *
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 */
34 /*$FreeBSD$*/
35
36 #include "osdep.h"
37 #include "irdma_hmc.h"
38 #include "irdma_defs.h"
39 #include "irdma_type.h"
40 #include "irdma_protos.h"
41 #include "irdma_uda.h"
42 #include "irdma_uda_d.h"
43
44 /**
45 * irdma_sc_access_ah() - Create, modify or delete AH
46 * @cqp: struct for cqp hw
47 * @info: ah information
48 * @op: Operation
49 * @scratch: u64 saved to be used during cqp completion
50 */
51 int
52 irdma_sc_access_ah(struct irdma_sc_cqp *cqp, struct irdma_ah_info *info,
53 u32 op, u64 scratch)
54 {
55 __le64 *wqe;
56 u64 qw1, qw2;
57
58 wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
59 if (!wqe)
60 return -ENOSPC;
61
62 set_64bit_val(wqe, IRDMA_BYTE_0, LS_64_1(info->mac_addr[5], 16) |
63 LS_64_1(info->mac_addr[4], 24) |
64 LS_64_1(info->mac_addr[3], 32) |
65 LS_64_1(info->mac_addr[2], 40) |
66 LS_64_1(info->mac_addr[1], 48) |
67 LS_64_1(info->mac_addr[0], 56));
68
69 qw1 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXLO, info->pd_idx) |
70 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_TC, info->tc_tos) |
71 FIELD_PREP(IRDMA_UDAQPC_VLANTAG, info->vlan_tag);
72
73 qw2 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ARPINDEX, info->dst_arpindex) |
74 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_FLOWLABEL, info->flow_label) |
75 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_HOPLIMIT, info->hop_ttl) |
76 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXHI, info->pd_idx >> 16);
77
78 if (!info->ipv4_valid) {
79 set_64bit_val(wqe, IRDMA_BYTE_40,
80 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
81 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
82 set_64bit_val(wqe, IRDMA_BYTE_32,
83 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
84 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
85
86 set_64bit_val(wqe, IRDMA_BYTE_56,
87 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->src_ip_addr[0]) |
88 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->src_ip_addr[1]));
89 set_64bit_val(wqe, IRDMA_BYTE_48,
90 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->src_ip_addr[2]) |
91 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[3]));
92 } else {
93 set_64bit_val(wqe, IRDMA_BYTE_32,
94 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
95
96 set_64bit_val(wqe, IRDMA_BYTE_48,
97 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[0]));
98 }
99
100 set_64bit_val(wqe, IRDMA_BYTE_8, qw1);
101 set_64bit_val(wqe, IRDMA_BYTE_16, qw2);
102
103 irdma_wmb(); /* need write block before writing WQE header */
104
105 set_64bit_val(
106 wqe, IRDMA_BYTE_24,
107 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_WQEVALID, cqp->polarity) |
108 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_OPCODE, op) |
109 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK, info->do_lpbk) |
110 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_IPV4VALID, info->ipv4_valid) |
111 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_AVIDX, info->ah_idx) |
112 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG, info->insert_vlan_tag));
113
114 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MANAGE_AH WQE", wqe,
115 IRDMA_CQP_WQE_SIZE * 8);
116 irdma_sc_cqp_post_sq(cqp);
117
118 return 0;
119 }
120
121 /**
122 * irdma_create_mg_ctx() - create a mcg context
123 * @info: multicast group context info
124 */
125 static int
126 irdma_create_mg_ctx(struct irdma_mcast_grp_info *info)
127 {
128 struct irdma_mcast_grp_ctx_entry_info *entry_info = NULL;
129 u8 idx = 0; /* index in the array */
130 u8 ctx_idx = 0; /* index in the MG context */
131
132 memset(info->dma_mem_mc.va, 0, IRDMA_MAX_MGS_PER_CTX * sizeof(u64));
133
134 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
135 entry_info = &info->mg_ctx_info[idx];
136 if (entry_info->valid_entry) {
137 set_64bit_val((__le64 *) info->dma_mem_mc.va,
138 ctx_idx * sizeof(u64),
139 FIELD_PREP(IRDMA_UDA_MGCTX_DESTPORT, entry_info->dest_port) |
140 FIELD_PREP(IRDMA_UDA_MGCTX_VALIDENT, entry_info->valid_entry) |
141 FIELD_PREP(IRDMA_UDA_MGCTX_QPID, entry_info->qp_id));
142 ctx_idx++;
143 }
144 }
145
146 return 0;
147 }
148
149 /**
150 * irdma_access_mcast_grp() - Access mcast group based on op
151 * @cqp: Control QP
152 * @info: multicast group context info
153 * @op: operation to perform
154 * @scratch: u64 saved to be used during cqp completion
155 */
156 int
157 irdma_access_mcast_grp(struct irdma_sc_cqp *cqp,
158 struct irdma_mcast_grp_info *info, u32 op,
159 u64 scratch)
160 {
161 __le64 *wqe;
162 int ret_code = 0;
163
164 if (info->mg_id >= IRDMA_UDA_MAX_FSI_MGS) {
165 irdma_debug(cqp->dev, IRDMA_DEBUG_WQE, "mg_id out of range\n");
166 return -EINVAL;
167 }
168
169 wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
170 if (!wqe) {
171 irdma_debug(cqp->dev, IRDMA_DEBUG_WQE, "ring full\n");
172 return -ENOSPC;
173 }
174
175 ret_code = irdma_create_mg_ctx(info);
176 if (ret_code)
177 return ret_code;
178
179 set_64bit_val(wqe, IRDMA_BYTE_32, info->dma_mem_mc.pa);
180 set_64bit_val(wqe, IRDMA_BYTE_16,
181 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANID, info->vlan_id) |
182 FIELD_PREP(IRDMA_UDA_CQPSQ_QS_HANDLE, info->qs_handle));
183 set_64bit_val(wqe, IRDMA_BYTE_0, LS_64_1(info->dest_mac_addr[5], 0) |
184 LS_64_1(info->dest_mac_addr[4], 8) |
185 LS_64_1(info->dest_mac_addr[3], 16) |
186 LS_64_1(info->dest_mac_addr[2], 24) |
187 LS_64_1(info->dest_mac_addr[1], 32) |
188 LS_64_1(info->dest_mac_addr[0], 40));
189 set_64bit_val(wqe, IRDMA_BYTE_8,
190 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID, info->hmc_fcn_id));
191
192 if (!info->ipv4_valid) {
193 set_64bit_val(wqe, IRDMA_BYTE_56,
194 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
195 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
196 set_64bit_val(wqe, IRDMA_BYTE_48,
197 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
198 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
199 } else {
200 set_64bit_val(wqe, IRDMA_BYTE_48,
201 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
202 }
203
204 irdma_wmb(); /* need write memory block before writing the WQE header. */
205
206 set_64bit_val(wqe, IRDMA_BYTE_24,
207 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_WQEVALID, cqp->polarity) |
208 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_OPCODE, op) |
209 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_MGIDX, info->mg_id) |
210 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANVALID, info->vlan_valid) |
211 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_IPV4VALID, info->ipv4_valid));
212
213 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MANAGE_MCG WQE", wqe,
214 IRDMA_CQP_WQE_SIZE * 8);
215 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MCG_HOST CTX WQE",
216 info->dma_mem_mc.va, IRDMA_MAX_MGS_PER_CTX * 8);
217 irdma_sc_cqp_post_sq(cqp);
218
219 return 0;
220 }
221
222 /**
223 * irdma_compare_mgs - Compares two multicast group structures
224 * @entry1: Multcast group info
225 * @entry2: Multcast group info in context
226 */
227 static bool
228 irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info *entry1,
229 struct irdma_mcast_grp_ctx_entry_info *entry2)
230 {
231 if (entry1->dest_port == entry2->dest_port &&
232 entry1->qp_id == entry2->qp_id)
233 return true;
234
235 return false;
236 }
237
238 /**
239 * irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx
240 * @ctx: Multcast group context
241 * @mg: Multcast group info
242 */
243 int
244 irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx,
245 struct irdma_mcast_grp_ctx_entry_info *mg)
246 {
247 u32 idx;
248 bool free_entry_found = false;
249 u32 free_entry_idx = 0;
250
251 /* find either an identical or a free entry for a multicast group */
252 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
253 if (ctx->mg_ctx_info[idx].valid_entry) {
254 if (irdma_compare_mgs(&ctx->mg_ctx_info[idx], mg)) {
255 ctx->mg_ctx_info[idx].use_cnt++;
256 return 0;
257 }
258 continue;
259 }
260 if (!free_entry_found) {
261 free_entry_found = true;
262 free_entry_idx = idx;
263 }
264 }
265
266 if (free_entry_found) {
267 ctx->mg_ctx_info[free_entry_idx] = *mg;
268 ctx->mg_ctx_info[free_entry_idx].valid_entry = true;
269 ctx->mg_ctx_info[free_entry_idx].use_cnt = 1;
270 ctx->no_of_mgs++;
271 return 0;
272 }
273
274 return -ENOMEM;
275 }
276
277 /**
278 * irdma_sc_del_mcast_grp - Delete mcast group
279 * @ctx: Multcast group context
280 * @mg: Multcast group info
281 *
282 * Finds and removes a specific mulicast group from context, all
283 * parameters must match to remove a multicast group.
284 */
285 int
286 irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info *ctx,
287 struct irdma_mcast_grp_ctx_entry_info *mg)
288 {
289 u32 idx;
290
291 /* find an entry in multicast group context */
292 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
293 if (!ctx->mg_ctx_info[idx].valid_entry)
294 continue;
295
296 if (irdma_compare_mgs(mg, &ctx->mg_ctx_info[idx])) {
297 ctx->mg_ctx_info[idx].use_cnt--;
298
299 if (!ctx->mg_ctx_info[idx].use_cnt) {
300 ctx->mg_ctx_info[idx].valid_entry = false;
301 ctx->no_of_mgs--;
302 /* Remove gap if element was not the last */
303 if (idx != ctx->no_of_mgs &&
304 ctx->no_of_mgs > 0) {
305 irdma_memcpy(&ctx->mg_ctx_info[idx],
306 &ctx->mg_ctx_info[ctx->no_of_mgs - 1],
307 sizeof(ctx->mg_ctx_info[idx]));
308 ctx->mg_ctx_info[ctx->no_of_mgs - 1].valid_entry = false;
309 }
310 }
311
312 return 0;
313 }
314 }
315
316 return -EINVAL;
317 }
Cache object: 808cf0b916283ba93ec8cee66c66cfb2
|