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