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 = LS_64(info->pd_idx, IRDMA_UDA_CQPSQ_MAV_PDINDEXLO) | 70 LS_64(info->tc_tos, IRDMA_UDA_CQPSQ_MAV_TC) | 71 LS_64(info->vlan_tag, IRDMA_UDAQPC_VLANTAG); 72 73 qw2 = LS_64(info->dst_arpindex, IRDMA_UDA_CQPSQ_MAV_ARPINDEX) | 74 LS_64(info->flow_label, IRDMA_UDA_CQPSQ_MAV_FLOWLABEL) | 75 LS_64(info->hop_ttl, IRDMA_UDA_CQPSQ_MAV_HOPLIMIT) | 76 LS_64(info->pd_idx >> 16, IRDMA_UDA_CQPSQ_MAV_PDINDEXHI); 77 78 if (!info->ipv4_valid) { 79 set_64bit_val(wqe, IRDMA_BYTE_40, 80 LS_64(info->dest_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR0) | 81 LS_64(info->dest_ip_addr[1], IRDMA_UDA_CQPSQ_MAV_ADDR1)); 82 set_64bit_val(wqe, IRDMA_BYTE_32, 83 LS_64(info->dest_ip_addr[2], IRDMA_UDA_CQPSQ_MAV_ADDR2) | 84 LS_64(info->dest_ip_addr[3], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 85 86 set_64bit_val(wqe, IRDMA_BYTE_56, 87 LS_64(info->src_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR0) | 88 LS_64(info->src_ip_addr[1], IRDMA_UDA_CQPSQ_MAV_ADDR1)); 89 set_64bit_val(wqe, IRDMA_BYTE_48, 90 LS_64(info->src_ip_addr[2], IRDMA_UDA_CQPSQ_MAV_ADDR2) | 91 LS_64(info->src_ip_addr[3], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 92 } else { 93 set_64bit_val(wqe, IRDMA_BYTE_32, 94 LS_64(info->dest_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 95 96 set_64bit_val(wqe, IRDMA_BYTE_48, 97 LS_64(info->src_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 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 LS_64(cqp->polarity, IRDMA_UDA_CQPSQ_MAV_WQEVALID) | 108 LS_64(op, IRDMA_UDA_CQPSQ_MAV_OPCODE) | 109 LS_64(info->do_lpbk, IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK) | 110 LS_64(info->ipv4_valid, IRDMA_UDA_CQPSQ_MAV_IPV4VALID) | 111 LS_64(info->ah_idx, IRDMA_UDA_CQPSQ_MAV_AVIDX) | 112 LS_64(info->insert_vlan_tag, 113 IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG)); 114 115 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MANAGE_AH WQE", wqe, 116 IRDMA_CQP_WQE_SIZE * 8); 117 irdma_sc_cqp_post_sq(cqp); 118 119 return 0; 120 } 121 122 /** 123 * irdma_create_mg_ctx() - create a mcg context 124 * @info: multicast group context info 125 */ 126 static int 127 irdma_create_mg_ctx(struct irdma_mcast_grp_info *info) 128 { 129 struct irdma_mcast_grp_ctx_entry_info *entry_info = NULL; 130 u8 idx = 0; /* index in the array */ 131 u8 ctx_idx = 0; /* index in the MG context */ 132 133 memset(info->dma_mem_mc.va, 0, IRDMA_MAX_MGS_PER_CTX * sizeof(u64)); 134 135 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) { 136 entry_info = &info->mg_ctx_info[idx]; 137 if (entry_info->valid_entry) { 138 set_64bit_val((__le64 *) info->dma_mem_mc.va, 139 ctx_idx * sizeof(u64), 140 LS_64(entry_info->dest_port, IRDMA_UDA_MGCTX_DESTPORT) | 141 LS_64(entry_info->valid_entry, IRDMA_UDA_MGCTX_VALIDENT) | 142 LS_64(entry_info->qp_id, IRDMA_UDA_MGCTX_QPID)); 143 ctx_idx++; 144 } 145 } 146 147 return 0; 148 } 149 150 /** 151 * irdma_access_mcast_grp() - Access mcast group based on op 152 * @cqp: Control QP 153 * @info: multicast group context info 154 * @op: operation to perform 155 * @scratch: u64 saved to be used during cqp completion 156 */ 157 int 158 irdma_access_mcast_grp(struct irdma_sc_cqp *cqp, 159 struct irdma_mcast_grp_info *info, u32 op, 160 u64 scratch) 161 { 162 __le64 *wqe; 163 int ret_code = 0; 164 165 if (info->mg_id >= IRDMA_UDA_MAX_FSI_MGS) { 166 irdma_debug(cqp->dev, IRDMA_DEBUG_WQE, "mg_id out of range\n"); 167 return -EINVAL; 168 } 169 170 wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); 171 if (!wqe) { 172 irdma_debug(cqp->dev, IRDMA_DEBUG_WQE, "ring full\n"); 173 return -ENOSPC; 174 } 175 176 ret_code = irdma_create_mg_ctx(info); 177 if (ret_code) 178 return ret_code; 179 180 set_64bit_val(wqe, IRDMA_BYTE_32, info->dma_mem_mc.pa); 181 set_64bit_val(wqe, IRDMA_BYTE_16, 182 LS_64(info->vlan_id, IRDMA_UDA_CQPSQ_MG_VLANID) | 183 LS_64(info->qs_handle, IRDMA_UDA_CQPSQ_QS_HANDLE)); 184 set_64bit_val(wqe, IRDMA_BYTE_0, LS_64_1(info->dest_mac_addr[5], 0) | 185 LS_64_1(info->dest_mac_addr[4], 8) | 186 LS_64_1(info->dest_mac_addr[3], 16) | 187 LS_64_1(info->dest_mac_addr[2], 24) | 188 LS_64_1(info->dest_mac_addr[1], 32) | 189 LS_64_1(info->dest_mac_addr[0], 40)); 190 set_64bit_val(wqe, IRDMA_BYTE_8, 191 LS_64(info->hmc_fcn_id, IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID)); 192 193 if (!info->ipv4_valid) { 194 set_64bit_val(wqe, IRDMA_BYTE_56, 195 LS_64(info->dest_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR0) | 196 LS_64(info->dest_ip_addr[1], IRDMA_UDA_CQPSQ_MAV_ADDR1)); 197 set_64bit_val(wqe, IRDMA_BYTE_48, 198 LS_64(info->dest_ip_addr[2], IRDMA_UDA_CQPSQ_MAV_ADDR2) | 199 LS_64(info->dest_ip_addr[3], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 200 } else { 201 set_64bit_val(wqe, IRDMA_BYTE_48, 202 LS_64(info->dest_ip_addr[0], IRDMA_UDA_CQPSQ_MAV_ADDR3)); 203 } 204 205 irdma_wmb(); /* need write memory block before writing the WQE header. */ 206 207 set_64bit_val(wqe, IRDMA_BYTE_24, 208 LS_64(cqp->polarity, IRDMA_UDA_CQPSQ_MG_WQEVALID) | 209 LS_64(op, IRDMA_UDA_CQPSQ_MG_OPCODE) | 210 LS_64(info->mg_id, IRDMA_UDA_CQPSQ_MG_MGIDX) | 211 LS_64(info->vlan_valid, IRDMA_UDA_CQPSQ_MG_VLANVALID) | 212 LS_64(info->ipv4_valid, IRDMA_UDA_CQPSQ_MG_IPV4VALID)); 213 214 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MANAGE_MCG WQE", wqe, 215 IRDMA_CQP_WQE_SIZE * 8); 216 irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MCG_HOST CTX WQE", 217 info->dma_mem_mc.va, IRDMA_MAX_MGS_PER_CTX * 8); 218 irdma_sc_cqp_post_sq(cqp); 219 220 return 0; 221 } 222 223 /** 224 * irdma_compare_mgs - Compares two multicast group structures 225 * @entry1: Multcast group info 226 * @entry2: Multcast group info in context 227 */ 228 static bool 229 irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info *entry1, 230 struct irdma_mcast_grp_ctx_entry_info *entry2) 231 { 232 if (entry1->dest_port == entry2->dest_port && 233 entry1->qp_id == entry2->qp_id) 234 return true; 235 236 return false; 237 } 238 239 /** 240 * irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx 241 * @ctx: Multcast group context 242 * @mg: Multcast group info 243 */ 244 int 245 irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx, 246 struct irdma_mcast_grp_ctx_entry_info *mg) 247 { 248 u32 idx; 249 bool free_entry_found = false; 250 u32 free_entry_idx = 0; 251 252 /* find either an identical or a free entry for a multicast group */ 253 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) { 254 if (ctx->mg_ctx_info[idx].valid_entry) { 255 if (irdma_compare_mgs(&ctx->mg_ctx_info[idx], mg)) { 256 ctx->mg_ctx_info[idx].use_cnt++; 257 return 0; 258 } 259 continue; 260 } 261 if (!free_entry_found) { 262 free_entry_found = true; 263 free_entry_idx = idx; 264 } 265 } 266 267 if (free_entry_found) { 268 ctx->mg_ctx_info[free_entry_idx] = *mg; 269 ctx->mg_ctx_info[free_entry_idx].valid_entry = true; 270 ctx->mg_ctx_info[free_entry_idx].use_cnt = 1; 271 ctx->no_of_mgs++; 272 return 0; 273 } 274 275 return -ENOMEM; 276 } 277 278 /** 279 * irdma_sc_del_mcast_grp - Delete mcast group 280 * @ctx: Multcast group context 281 * @mg: Multcast group info 282 * 283 * Finds and removes a specific mulicast group from context, all 284 * parameters must match to remove a multicast group. 285 */ 286 int 287 irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info *ctx, 288 struct irdma_mcast_grp_ctx_entry_info *mg) 289 { 290 u32 idx; 291 292 /* find an entry in multicast group context */ 293 for (idx = 0; idx < IRDMA_MAX_MGS_PER_CTX; idx++) { 294 if (!ctx->mg_ctx_info[idx].valid_entry) 295 continue; 296 297 if (irdma_compare_mgs(mg, &ctx->mg_ctx_info[idx])) { 298 ctx->mg_ctx_info[idx].use_cnt--; 299 300 if (!ctx->mg_ctx_info[idx].use_cnt) { 301 ctx->mg_ctx_info[idx].valid_entry = false; 302 ctx->no_of_mgs--; 303 /* Remove gap if element was not the last */ 304 if (idx != ctx->no_of_mgs && 305 ctx->no_of_mgs > 0) { 306 irdma_memcpy(&ctx->mg_ctx_info[idx], 307 &ctx->mg_ctx_info[ctx->no_of_mgs - 1], 308 sizeof(ctx->mg_ctx_info[idx])); 309 ctx->mg_ctx_info[ctx->no_of_mgs - 1].valid_entry = false; 310 } 311 } 312 313 return 0; 314 } 315 } 316 317 return -EINVAL; 318 } 319