xref: /openbmc/linux/drivers/infiniband/hw/irdma/uda.c (revision ea7596c1)
1dd90451fSMustafa Ismail // SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
2dd90451fSMustafa Ismail /* Copyright (c) 2016 - 2021 Intel Corporation */
3b6459415SJakub Kicinski #include <linux/etherdevice.h>
4b6459415SJakub Kicinski 
5dd90451fSMustafa Ismail #include "osdep.h"
6dd90451fSMustafa Ismail #include "hmc.h"
7dd90451fSMustafa Ismail #include "defs.h"
8dd90451fSMustafa Ismail #include "type.h"
9dd90451fSMustafa Ismail #include "protos.h"
10dd90451fSMustafa Ismail #include "uda.h"
11dd90451fSMustafa Ismail #include "uda_d.h"
12dd90451fSMustafa Ismail 
13dd90451fSMustafa Ismail /**
14dd90451fSMustafa Ismail  * irdma_sc_access_ah() - Create, modify or delete AH
15dd90451fSMustafa Ismail  * @cqp: struct for cqp hw
16dd90451fSMustafa Ismail  * @info: ah information
17dd90451fSMustafa Ismail  * @op: Operation
18dd90451fSMustafa Ismail  * @scratch: u64 saved to be used during cqp completion
19dd90451fSMustafa Ismail  */
irdma_sc_access_ah(struct irdma_sc_cqp * cqp,struct irdma_ah_info * info,u32 op,u64 scratch)202c4b14eaSShiraz Saleem int irdma_sc_access_ah(struct irdma_sc_cqp *cqp, struct irdma_ah_info *info,
21dd90451fSMustafa Ismail 		       u32 op, u64 scratch)
22dd90451fSMustafa Ismail {
23dd90451fSMustafa Ismail 	__le64 *wqe;
24dd90451fSMustafa Ismail 	u64 qw1, qw2;
25dd90451fSMustafa Ismail 
26dd90451fSMustafa Ismail 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
27dd90451fSMustafa Ismail 	if (!wqe)
282c4b14eaSShiraz Saleem 		return -ENOMEM;
29dd90451fSMustafa Ismail 
30dd90451fSMustafa Ismail 	set_64bit_val(wqe, 0, ether_addr_to_u64(info->mac_addr) << 16);
31dd90451fSMustafa Ismail 	qw1 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXLO, info->pd_idx) |
32dd90451fSMustafa Ismail 	      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_TC, info->tc_tos) |
33dd90451fSMustafa Ismail 	      FIELD_PREP(IRDMA_UDAQPC_VLANTAG, info->vlan_tag);
34dd90451fSMustafa Ismail 
35dd90451fSMustafa Ismail 	qw2 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ARPINDEX, info->dst_arpindex) |
36dd90451fSMustafa Ismail 	      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_FLOWLABEL, info->flow_label) |
37dd90451fSMustafa Ismail 	      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_HOPLIMIT, info->hop_ttl) |
38dd90451fSMustafa Ismail 	      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXHI, info->pd_idx >> 16);
39dd90451fSMustafa Ismail 
40dd90451fSMustafa Ismail 	if (!info->ipv4_valid) {
41dd90451fSMustafa Ismail 		set_64bit_val(wqe, 40,
42dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
43dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
44dd90451fSMustafa Ismail 		set_64bit_val(wqe, 32,
45dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
46dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
47dd90451fSMustafa Ismail 
48dd90451fSMustafa Ismail 		set_64bit_val(wqe, 56,
49dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->src_ip_addr[0]) |
50dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->src_ip_addr[1]));
51dd90451fSMustafa Ismail 		set_64bit_val(wqe, 48,
52dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->src_ip_addr[2]) |
53dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[3]));
54dd90451fSMustafa Ismail 	} else {
55dd90451fSMustafa Ismail 		set_64bit_val(wqe, 32,
56dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
57dd90451fSMustafa Ismail 
58dd90451fSMustafa Ismail 		set_64bit_val(wqe, 48,
59dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[0]));
60dd90451fSMustafa Ismail 	}
61dd90451fSMustafa Ismail 
62dd90451fSMustafa Ismail 	set_64bit_val(wqe, 8, qw1);
63dd90451fSMustafa Ismail 	set_64bit_val(wqe, 16, qw2);
64dd90451fSMustafa Ismail 
65dd90451fSMustafa Ismail 	dma_wmb(); /* need write block before writing WQE header */
66dd90451fSMustafa Ismail 
67dd90451fSMustafa Ismail 	set_64bit_val(
68dd90451fSMustafa Ismail 		wqe, 24,
69dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_WQEVALID, cqp->polarity) |
70dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_OPCODE, op) |
71dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK, info->do_lpbk) |
72dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_IPV4VALID, info->ipv4_valid) |
73dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_AVIDX, info->ah_idx) |
74dd90451fSMustafa Ismail 		FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG, info->insert_vlan_tag));
75dd90451fSMustafa Ismail 
76dd90451fSMustafa Ismail 	print_hex_dump_debug("WQE: MANAGE_AH WQE", DUMP_PREFIX_OFFSET, 16, 8,
77dd90451fSMustafa Ismail 			     wqe, IRDMA_CQP_WQE_SIZE * 8, false);
78dd90451fSMustafa Ismail 	irdma_sc_cqp_post_sq(cqp);
79dd90451fSMustafa Ismail 
80dd90451fSMustafa Ismail 	return 0;
81dd90451fSMustafa Ismail }
82dd90451fSMustafa Ismail 
83dd90451fSMustafa Ismail /**
84dd90451fSMustafa Ismail  * irdma_create_mg_ctx() - create a mcg context
85dd90451fSMustafa Ismail  * @info: multicast group context info
86dd90451fSMustafa Ismail  */
irdma_create_mg_ctx(struct irdma_mcast_grp_info * info)87*ea7596c1SZhu Yanjun static void irdma_create_mg_ctx(struct irdma_mcast_grp_info *info)
88dd90451fSMustafa Ismail {
89dd90451fSMustafa Ismail 	struct irdma_mcast_grp_ctx_entry_info *entry_info = NULL;
90dd90451fSMustafa Ismail 	u8 idx = 0; /* index in the array */
91dd90451fSMustafa Ismail 	u8 ctx_idx = 0; /* index in the MG context */
92dd90451fSMustafa Ismail 
93dd90451fSMustafa Ismail 	memset(info->dma_mem_mc.va, 0, IRDMA_MAX_MGS_PER_CTX * sizeof(u64));
94dd90451fSMustafa Ismail 
95dd90451fSMustafa Ismail 	for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
96dd90451fSMustafa Ismail 		entry_info = &info->mg_ctx_info[idx];
97dd90451fSMustafa Ismail 		if (entry_info->valid_entry) {
98dd90451fSMustafa Ismail 			set_64bit_val((__le64 *)info->dma_mem_mc.va,
99dd90451fSMustafa Ismail 				      ctx_idx * sizeof(u64),
100dd90451fSMustafa Ismail 				      FIELD_PREP(IRDMA_UDA_MGCTX_DESTPORT, entry_info->dest_port) |
101dd90451fSMustafa Ismail 				      FIELD_PREP(IRDMA_UDA_MGCTX_VALIDENT, entry_info->valid_entry) |
102dd90451fSMustafa Ismail 				      FIELD_PREP(IRDMA_UDA_MGCTX_QPID, entry_info->qp_id));
103dd90451fSMustafa Ismail 			ctx_idx++;
104dd90451fSMustafa Ismail 		}
105dd90451fSMustafa Ismail 	}
106dd90451fSMustafa Ismail }
107dd90451fSMustafa Ismail 
108dd90451fSMustafa Ismail /**
109dd90451fSMustafa Ismail  * irdma_access_mcast_grp() - Access mcast group based on op
110dd90451fSMustafa Ismail  * @cqp: Control QP
111dd90451fSMustafa Ismail  * @info: multicast group context info
112dd90451fSMustafa Ismail  * @op: operation to perform
113dd90451fSMustafa Ismail  * @scratch: u64 saved to be used during cqp completion
114dd90451fSMustafa Ismail  */
irdma_access_mcast_grp(struct irdma_sc_cqp * cqp,struct irdma_mcast_grp_info * info,u32 op,u64 scratch)1152c4b14eaSShiraz Saleem int irdma_access_mcast_grp(struct irdma_sc_cqp *cqp,
1162c4b14eaSShiraz Saleem 			   struct irdma_mcast_grp_info *info, u32 op,
1172c4b14eaSShiraz Saleem 			   u64 scratch)
118dd90451fSMustafa Ismail {
119dd90451fSMustafa Ismail 	__le64 *wqe;
120dd90451fSMustafa Ismail 
121dd90451fSMustafa Ismail 	if (info->mg_id >= IRDMA_UDA_MAX_FSI_MGS) {
122dd90451fSMustafa Ismail 		ibdev_dbg(to_ibdev(cqp->dev), "WQE: mg_id out of range\n");
1232c4b14eaSShiraz Saleem 		return -EINVAL;
124dd90451fSMustafa Ismail 	}
125dd90451fSMustafa Ismail 
126dd90451fSMustafa Ismail 	wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
127dd90451fSMustafa Ismail 	if (!wqe) {
128dd90451fSMustafa Ismail 		ibdev_dbg(to_ibdev(cqp->dev), "WQE: ring full\n");
1292c4b14eaSShiraz Saleem 		return -ENOMEM;
130dd90451fSMustafa Ismail 	}
131dd90451fSMustafa Ismail 
132*ea7596c1SZhu Yanjun 	irdma_create_mg_ctx(info);
133dd90451fSMustafa Ismail 
134dd90451fSMustafa Ismail 	set_64bit_val(wqe, 32, info->dma_mem_mc.pa);
135dd90451fSMustafa Ismail 	set_64bit_val(wqe, 16,
136dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANID, info->vlan_id) |
137dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_QS_HANDLE, info->qs_handle));
138dd90451fSMustafa Ismail 	set_64bit_val(wqe, 0, ether_addr_to_u64(info->dest_mac_addr));
139dd90451fSMustafa Ismail 	set_64bit_val(wqe, 8,
140dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID, info->hmc_fcn_id));
141dd90451fSMustafa Ismail 
142dd90451fSMustafa Ismail 	if (!info->ipv4_valid) {
143dd90451fSMustafa Ismail 		set_64bit_val(wqe, 56,
144dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0]) |
145dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1]));
146dd90451fSMustafa Ismail 		set_64bit_val(wqe, 48,
147dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2]) |
148dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3]));
149dd90451fSMustafa Ismail 	} else {
150dd90451fSMustafa Ismail 		set_64bit_val(wqe, 48,
151dd90451fSMustafa Ismail 			      FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0]));
152dd90451fSMustafa Ismail 	}
153dd90451fSMustafa Ismail 
154dd90451fSMustafa Ismail 	dma_wmb(); /* need write memory block before writing the WQE header. */
155dd90451fSMustafa Ismail 
156dd90451fSMustafa Ismail 	set_64bit_val(wqe, 24,
157dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_WQEVALID, cqp->polarity) |
158dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_OPCODE, op) |
159dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_MGIDX, info->mg_id) |
160dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANVALID, info->vlan_valid) |
161dd90451fSMustafa Ismail 		      FIELD_PREP(IRDMA_UDA_CQPSQ_MG_IPV4VALID, info->ipv4_valid));
162dd90451fSMustafa Ismail 
163dd90451fSMustafa Ismail 	print_hex_dump_debug("WQE: MANAGE_MCG WQE", DUMP_PREFIX_OFFSET, 16, 8,
164dd90451fSMustafa Ismail 			     wqe, IRDMA_CQP_WQE_SIZE * 8, false);
165dd90451fSMustafa Ismail 	print_hex_dump_debug("WQE: MCG_HOST CTX WQE", DUMP_PREFIX_OFFSET, 16,
166dd90451fSMustafa Ismail 			     8, info->dma_mem_mc.va,
167dd90451fSMustafa Ismail 			     IRDMA_MAX_MGS_PER_CTX * 8, false);
168dd90451fSMustafa Ismail 	irdma_sc_cqp_post_sq(cqp);
169dd90451fSMustafa Ismail 
170dd90451fSMustafa Ismail 	return 0;
171dd90451fSMustafa Ismail }
172dd90451fSMustafa Ismail 
173dd90451fSMustafa Ismail /**
174dd90451fSMustafa Ismail  * irdma_compare_mgs - Compares two multicast group structures
175dd90451fSMustafa Ismail  * @entry1: Multcast group info
176dd90451fSMustafa Ismail  * @entry2: Multcast group info in context
177dd90451fSMustafa Ismail  */
irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info * entry1,struct irdma_mcast_grp_ctx_entry_info * entry2)178dd90451fSMustafa Ismail static bool irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info *entry1,
179dd90451fSMustafa Ismail 			      struct irdma_mcast_grp_ctx_entry_info *entry2)
180dd90451fSMustafa Ismail {
181dd90451fSMustafa Ismail 	if (entry1->dest_port == entry2->dest_port &&
182dd90451fSMustafa Ismail 	    entry1->qp_id == entry2->qp_id)
183dd90451fSMustafa Ismail 		return true;
184dd90451fSMustafa Ismail 
185dd90451fSMustafa Ismail 	return false;
186dd90451fSMustafa Ismail }
187dd90451fSMustafa Ismail 
188dd90451fSMustafa Ismail /**
189dd90451fSMustafa Ismail  * irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx
190dd90451fSMustafa Ismail  * @ctx: Multcast group context
191dd90451fSMustafa Ismail  * @mg: Multcast group info
192dd90451fSMustafa Ismail  */
irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info * ctx,struct irdma_mcast_grp_ctx_entry_info * mg)1932c4b14eaSShiraz Saleem int irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx,
194dd90451fSMustafa Ismail 			   struct irdma_mcast_grp_ctx_entry_info *mg)
195dd90451fSMustafa Ismail {
196dd90451fSMustafa Ismail 	u32 idx;
197dd90451fSMustafa Ismail 	bool free_entry_found = false;
198dd90451fSMustafa Ismail 	u32 free_entry_idx = 0;
199dd90451fSMustafa Ismail 
200dd90451fSMustafa Ismail 	/* find either an identical or a free entry for a multicast group */
201dd90451fSMustafa Ismail 	for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
202dd90451fSMustafa Ismail 		if (ctx->mg_ctx_info[idx].valid_entry) {
203dd90451fSMustafa Ismail 			if (irdma_compare_mgs(&ctx->mg_ctx_info[idx], mg)) {
204dd90451fSMustafa Ismail 				ctx->mg_ctx_info[idx].use_cnt++;
205dd90451fSMustafa Ismail 				return 0;
206dd90451fSMustafa Ismail 			}
207dd90451fSMustafa Ismail 			continue;
208dd90451fSMustafa Ismail 		}
209dd90451fSMustafa Ismail 		if (!free_entry_found) {
210dd90451fSMustafa Ismail 			free_entry_found = true;
211dd90451fSMustafa Ismail 			free_entry_idx = idx;
212dd90451fSMustafa Ismail 		}
213dd90451fSMustafa Ismail 	}
214dd90451fSMustafa Ismail 
215dd90451fSMustafa Ismail 	if (free_entry_found) {
216dd90451fSMustafa Ismail 		ctx->mg_ctx_info[free_entry_idx] = *mg;
217dd90451fSMustafa Ismail 		ctx->mg_ctx_info[free_entry_idx].valid_entry = true;
218dd90451fSMustafa Ismail 		ctx->mg_ctx_info[free_entry_idx].use_cnt = 1;
219dd90451fSMustafa Ismail 		ctx->no_of_mgs++;
220dd90451fSMustafa Ismail 		return 0;
221dd90451fSMustafa Ismail 	}
222dd90451fSMustafa Ismail 
2232c4b14eaSShiraz Saleem 	return -ENOMEM;
224dd90451fSMustafa Ismail }
225dd90451fSMustafa Ismail 
226dd90451fSMustafa Ismail /**
227dd90451fSMustafa Ismail  * irdma_sc_del_mcast_grp - Delete mcast group
228dd90451fSMustafa Ismail  * @ctx: Multcast group context
229dd90451fSMustafa Ismail  * @mg: Multcast group info
230dd90451fSMustafa Ismail  *
231dd90451fSMustafa Ismail  * Finds and removes a specific mulicast group from context, all
232dd90451fSMustafa Ismail  * parameters must match to remove a multicast group.
233dd90451fSMustafa Ismail  */
irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info * ctx,struct irdma_mcast_grp_ctx_entry_info * mg)2342c4b14eaSShiraz Saleem int irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info *ctx,
235dd90451fSMustafa Ismail 			   struct irdma_mcast_grp_ctx_entry_info *mg)
236dd90451fSMustafa Ismail {
237dd90451fSMustafa Ismail 	u32 idx;
238dd90451fSMustafa Ismail 
239dd90451fSMustafa Ismail 	/* find an entry in multicast group context */
240dd90451fSMustafa Ismail 	for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
241dd90451fSMustafa Ismail 		if (!ctx->mg_ctx_info[idx].valid_entry)
242dd90451fSMustafa Ismail 			continue;
243dd90451fSMustafa Ismail 
244dd90451fSMustafa Ismail 		if (irdma_compare_mgs(mg, &ctx->mg_ctx_info[idx])) {
245dd90451fSMustafa Ismail 			ctx->mg_ctx_info[idx].use_cnt--;
246dd90451fSMustafa Ismail 
247dd90451fSMustafa Ismail 			if (!ctx->mg_ctx_info[idx].use_cnt) {
248dd90451fSMustafa Ismail 				ctx->mg_ctx_info[idx].valid_entry = false;
249dd90451fSMustafa Ismail 				ctx->no_of_mgs--;
250dd90451fSMustafa Ismail 				/* Remove gap if element was not the last */
251dd90451fSMustafa Ismail 				if (idx != ctx->no_of_mgs &&
252dd90451fSMustafa Ismail 				    ctx->no_of_mgs > 0) {
253dd90451fSMustafa Ismail 					memcpy(&ctx->mg_ctx_info[idx],
254dd90451fSMustafa Ismail 					       &ctx->mg_ctx_info[ctx->no_of_mgs - 1],
255dd90451fSMustafa Ismail 					       sizeof(ctx->mg_ctx_info[idx]));
256dd90451fSMustafa Ismail 					ctx->mg_ctx_info[ctx->no_of_mgs - 1].valid_entry = false;
257dd90451fSMustafa Ismail 				}
258dd90451fSMustafa Ismail 			}
259dd90451fSMustafa Ismail 
260dd90451fSMustafa Ismail 			return 0;
261dd90451fSMustafa Ismail 		}
262dd90451fSMustafa Ismail 	}
263dd90451fSMustafa Ismail 
2642c4b14eaSShiraz Saleem 	return -EINVAL;
265dd90451fSMustafa Ismail }
266