1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2016 - 2021 Intel Corporation */
3 #include <linux/etherdevice.h>
14 * irdma_sc_access_ah() - Create, modify or delete AH
15 * @cqp: struct for cqp hw
16 * @info: ah information
18 * @scratch: u64 saved to be used during cqp completion
20 int irdma_sc_access_ah(struct irdma_sc_cqp
*cqp
, struct irdma_ah_info
*info
,
26 wqe
= irdma_sc_cqp_get_next_send_wqe(cqp
, scratch
);
30 set_64bit_val(wqe
, 0, ether_addr_to_u64(info
->mac_addr
) << 16);
31 qw1
= FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXLO
, info
->pd_idx
) |
32 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_TC
, info
->tc_tos
) |
33 FIELD_PREP(IRDMA_UDAQPC_VLANTAG
, info
->vlan_tag
);
35 qw2
= FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ARPINDEX
, info
->dst_arpindex
) |
36 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_FLOWLABEL
, info
->flow_label
) |
37 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_HOPLIMIT
, info
->hop_ttl
) |
38 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXHI
, info
->pd_idx
>> 16);
40 if (!info
->ipv4_valid
) {
41 set_64bit_val(wqe
, 40,
42 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0
, info
->dest_ip_addr
[0]) |
43 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1
, info
->dest_ip_addr
[1]));
44 set_64bit_val(wqe
, 32,
45 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2
, info
->dest_ip_addr
[2]) |
46 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->dest_ip_addr
[3]));
48 set_64bit_val(wqe
, 56,
49 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0
, info
->src_ip_addr
[0]) |
50 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1
, info
->src_ip_addr
[1]));
51 set_64bit_val(wqe
, 48,
52 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2
, info
->src_ip_addr
[2]) |
53 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->src_ip_addr
[3]));
55 set_64bit_val(wqe
, 32,
56 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->dest_ip_addr
[0]));
58 set_64bit_val(wqe
, 48,
59 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->src_ip_addr
[0]));
62 set_64bit_val(wqe
, 8, qw1
);
63 set_64bit_val(wqe
, 16, qw2
);
65 dma_wmb(); /* need write block before writing WQE header */
69 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_WQEVALID
, cqp
->polarity
) |
70 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_OPCODE
, op
) |
71 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK
, info
->do_lpbk
) |
72 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_IPV4VALID
, info
->ipv4_valid
) |
73 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_AVIDX
, info
->ah_idx
) |
74 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG
, info
->insert_vlan_tag
));
76 print_hex_dump_debug("WQE: MANAGE_AH WQE", DUMP_PREFIX_OFFSET
, 16, 8,
77 wqe
, IRDMA_CQP_WQE_SIZE
* 8, false);
78 irdma_sc_cqp_post_sq(cqp
);
84 * irdma_create_mg_ctx() - create a mcg context
85 * @info: multicast group context info
87 static void irdma_create_mg_ctx(struct irdma_mcast_grp_info
*info
)
89 struct irdma_mcast_grp_ctx_entry_info
*entry_info
= NULL
;
90 u8 idx
= 0; /* index in the array */
91 u8 ctx_idx
= 0; /* index in the MG context */
93 memset(info
->dma_mem_mc
.va
, 0, IRDMA_MAX_MGS_PER_CTX
* sizeof(u64
));
95 for (idx
= 0; idx
< IRDMA_MAX_MGS_PER_CTX
; idx
++) {
96 entry_info
= &info
->mg_ctx_info
[idx
];
97 if (entry_info
->valid_entry
) {
98 set_64bit_val((__le64
*)info
->dma_mem_mc
.va
,
99 ctx_idx
* sizeof(u64
),
100 FIELD_PREP(IRDMA_UDA_MGCTX_DESTPORT
, entry_info
->dest_port
) |
101 FIELD_PREP(IRDMA_UDA_MGCTX_VALIDENT
, entry_info
->valid_entry
) |
102 FIELD_PREP(IRDMA_UDA_MGCTX_QPID
, entry_info
->qp_id
));
109 * irdma_access_mcast_grp() - Access mcast group based on op
111 * @info: multicast group context info
112 * @op: operation to perform
113 * @scratch: u64 saved to be used during cqp completion
115 int irdma_access_mcast_grp(struct irdma_sc_cqp
*cqp
,
116 struct irdma_mcast_grp_info
*info
, u32 op
,
121 if (info
->mg_id
>= IRDMA_UDA_MAX_FSI_MGS
) {
122 ibdev_dbg(to_ibdev(cqp
->dev
), "WQE: mg_id out of range\n");
126 wqe
= irdma_sc_cqp_get_next_send_wqe(cqp
, scratch
);
128 ibdev_dbg(to_ibdev(cqp
->dev
), "WQE: ring full\n");
132 irdma_create_mg_ctx(info
);
134 set_64bit_val(wqe
, 32, info
->dma_mem_mc
.pa
);
135 set_64bit_val(wqe
, 16,
136 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANID
, info
->vlan_id
) |
137 FIELD_PREP(IRDMA_UDA_CQPSQ_QS_HANDLE
, info
->qs_handle
));
138 set_64bit_val(wqe
, 0, ether_addr_to_u64(info
->dest_mac_addr
));
139 set_64bit_val(wqe
, 8,
140 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID
, info
->hmc_fcn_id
));
142 if (!info
->ipv4_valid
) {
143 set_64bit_val(wqe
, 56,
144 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0
, info
->dest_ip_addr
[0]) |
145 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1
, info
->dest_ip_addr
[1]));
146 set_64bit_val(wqe
, 48,
147 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2
, info
->dest_ip_addr
[2]) |
148 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->dest_ip_addr
[3]));
150 set_64bit_val(wqe
, 48,
151 FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3
, info
->dest_ip_addr
[0]));
154 dma_wmb(); /* need write memory block before writing the WQE header. */
156 set_64bit_val(wqe
, 24,
157 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_WQEVALID
, cqp
->polarity
) |
158 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_OPCODE
, op
) |
159 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_MGIDX
, info
->mg_id
) |
160 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANVALID
, info
->vlan_valid
) |
161 FIELD_PREP(IRDMA_UDA_CQPSQ_MG_IPV4VALID
, info
->ipv4_valid
));
163 print_hex_dump_debug("WQE: MANAGE_MCG WQE", DUMP_PREFIX_OFFSET
, 16, 8,
164 wqe
, IRDMA_CQP_WQE_SIZE
* 8, false);
165 print_hex_dump_debug("WQE: MCG_HOST CTX WQE", DUMP_PREFIX_OFFSET
, 16,
166 8, info
->dma_mem_mc
.va
,
167 IRDMA_MAX_MGS_PER_CTX
* 8, false);
168 irdma_sc_cqp_post_sq(cqp
);
174 * irdma_compare_mgs - Compares two multicast group structures
175 * @entry1: Multcast group info
176 * @entry2: Multcast group info in context
178 static bool irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info
*entry1
,
179 struct irdma_mcast_grp_ctx_entry_info
*entry2
)
181 if (entry1
->dest_port
== entry2
->dest_port
&&
182 entry1
->qp_id
== entry2
->qp_id
)
189 * irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx
190 * @ctx: Multcast group context
191 * @mg: Multcast group info
193 int irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info
*ctx
,
194 struct irdma_mcast_grp_ctx_entry_info
*mg
)
197 bool free_entry_found
= false;
198 u32 free_entry_idx
= 0;
200 /* find either an identical or a free entry for a multicast group */
201 for (idx
= 0; idx
< IRDMA_MAX_MGS_PER_CTX
; idx
++) {
202 if (ctx
->mg_ctx_info
[idx
].valid_entry
) {
203 if (irdma_compare_mgs(&ctx
->mg_ctx_info
[idx
], mg
)) {
204 ctx
->mg_ctx_info
[idx
].use_cnt
++;
209 if (!free_entry_found
) {
210 free_entry_found
= true;
211 free_entry_idx
= idx
;
215 if (free_entry_found
) {
216 ctx
->mg_ctx_info
[free_entry_idx
] = *mg
;
217 ctx
->mg_ctx_info
[free_entry_idx
].valid_entry
= true;
218 ctx
->mg_ctx_info
[free_entry_idx
].use_cnt
= 1;
227 * irdma_sc_del_mcast_grp - Delete mcast group
228 * @ctx: Multcast group context
229 * @mg: Multcast group info
231 * Finds and removes a specific mulicast group from context, all
232 * parameters must match to remove a multicast group.
234 int irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info
*ctx
,
235 struct irdma_mcast_grp_ctx_entry_info
*mg
)
239 /* find an entry in multicast group context */
240 for (idx
= 0; idx
< IRDMA_MAX_MGS_PER_CTX
; idx
++) {
241 if (!ctx
->mg_ctx_info
[idx
].valid_entry
)
244 if (irdma_compare_mgs(mg
, &ctx
->mg_ctx_info
[idx
])) {
245 ctx
->mg_ctx_info
[idx
].use_cnt
--;
247 if (!ctx
->mg_ctx_info
[idx
].use_cnt
) {
248 ctx
->mg_ctx_info
[idx
].valid_entry
= false;
250 /* Remove gap if element was not the last */
251 if (idx
!= ctx
->no_of_mgs
&&
252 ctx
->no_of_mgs
> 0) {
253 memcpy(&ctx
->mg_ctx_info
[idx
],
254 &ctx
->mg_ctx_info
[ctx
->no_of_mgs
- 1],
255 sizeof(ctx
->mg_ctx_info
[idx
]));
256 ctx
->mg_ctx_info
[ctx
->no_of_mgs
- 1].valid_entry
= false;