// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2016 - 2021 Intel Corporation */
#include <linux/etherdevice.h>
#include "osdep.h"
#include "hmc.h"
#include "defs.h"
#include "type.h"
#include "protos.h"
#include "uda.h"
#include "uda_d.h"
/**
* irdma_sc_access_ah ( ) - Create , modify or delete AH
* @ cqp : struct for cqp hw
* @ info : ah information
* @ op : Operation
* @ scratch : u64 saved to be used during cqp completion
*/
int irdma_sc_access_ah(struct irdma_sc_cqp *cqp, struct irdma_ah_info *info,
u32 op, u64 scratch)
{
__le64 *wqe;
u64 qw1, qw2;
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
if (!wqe)
return -ENOMEM;
set_64bit_val(wqe, 0 , ether_addr_to_u64(info->mac_addr) << 16 );
qw1 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXLO, info->pd_idx) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_TC, info->tc_tos) |
FIELD_PREP(IRDMA_UDAQPC_VLANTAG, info->vlan_tag);
qw2 = FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ARPINDEX, info->dst_arpindex) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_FLOWLABEL, info->flow_label) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_HOPLIMIT, info->hop_ttl) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_PDINDEXHI, info->pd_idx >> 16 );
if (!info->ipv4_valid) {
set_64bit_val(wqe, 40 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1 ]));
set_64bit_val(wqe, 32 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3 ]));
set_64bit_val(wqe, 56 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->src_ip_addr[0 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->src_ip_addr[1 ]));
set_64bit_val(wqe, 48 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->src_ip_addr[2 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[3 ]));
} else {
set_64bit_val(wqe, 32 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0 ]));
set_64bit_val(wqe, 48 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->src_ip_addr[0 ]));
}
set_64bit_val(wqe, 8 , qw1);
set_64bit_val(wqe, 16 , qw2);
dma_wmb(); /* need write block before writing WQE header */
set_64bit_val(
wqe, 24 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_OPCODE, op) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK, info->do_lpbk) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_IPV4VALID, info->ipv4_valid) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_AVIDX, info->ah_idx) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_INSERTVLANTAG, info->insert_vlan_tag));
print_hex_dump_debug("WQE: MANAGE_AH WQE" , DUMP_PREFIX_OFFSET, 16 , 8 ,
wqe, IRDMA_CQP_WQE_SIZE * 8 , false );
irdma_sc_cqp_post_sq(cqp);
return 0 ;
}
/**
* irdma_create_mg_ctx ( ) - create a mcg context
* @ info : multicast group context info
*/
static void irdma_create_mg_ctx(struct irdma_mcast_grp_info *info)
{
struct irdma_mcast_grp_ctx_entry_info *entry_info = NULL;
u8 idx = 0 ; /* index in the array */
u8 ctx_idx = 0 ; /* index in the MG context */
memset(info->dma_mem_mc.va, 0 , IRDMA_MAX_MGS_PER_CTX * sizeof (u64));
for (idx = 0 ; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
entry_info = &info->mg_ctx_info[idx];
if (entry_info->valid_entry) {
set_64bit_val((__le64 *)info->dma_mem_mc.va,
ctx_idx * sizeof (u64),
FIELD_PREP(IRDMA_UDA_MGCTX_DESTPORT, entry_info->dest_port) |
FIELD_PREP(IRDMA_UDA_MGCTX_VALIDENT, entry_info->valid_entry) |
FIELD_PREP(IRDMA_UDA_MGCTX_QPID, entry_info->qp_id));
ctx_idx++;
}
}
}
/**
* irdma_access_mcast_grp ( ) - Access mcast group based on op
* @ cqp : Control QP
* @ info : multicast group context info
* @ op : operation to perform
* @ scratch : u64 saved to be used during cqp completion
*/
int irdma_access_mcast_grp(struct irdma_sc_cqp *cqp,
struct irdma_mcast_grp_info *info, u32 op,
u64 scratch)
{
__le64 *wqe;
if (info->mg_id >= IRDMA_UDA_MAX_FSI_MGS) {
ibdev_dbg(to_ibdev(cqp->dev), "WQE: mg_id out of range\n" );
return -EINVAL;
}
wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch);
if (!wqe) {
ibdev_dbg(to_ibdev(cqp->dev), "WQE: ring full\n" );
return -ENOMEM;
}
irdma_create_mg_ctx(info);
set_64bit_val(wqe, 32 , info->dma_mem_mc.pa);
set_64bit_val(wqe, 16 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANID, info->vlan_id) |
FIELD_PREP(IRDMA_UDA_CQPSQ_QS_HANDLE, info->qs_handle));
set_64bit_val(wqe, 0 , ether_addr_to_u64(info->dest_mac_addr));
set_64bit_val(wqe, 8 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_HMC_FCN_ID, info->hmc_fcn_id));
if (!info->ipv4_valid) {
set_64bit_val(wqe, 56 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR0, info->dest_ip_addr[0 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR1, info->dest_ip_addr[1 ]));
set_64bit_val(wqe, 48 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR2, info->dest_ip_addr[2 ]) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[3 ]));
} else {
set_64bit_val(wqe, 48 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MAV_ADDR3, info->dest_ip_addr[0 ]));
}
dma_wmb(); /* need write memory block before writing the WQE header. */
set_64bit_val(wqe, 24 ,
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_WQEVALID, cqp->polarity) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_OPCODE, op) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_MGIDX, info->mg_id) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_VLANVALID, info->vlan_valid) |
FIELD_PREP(IRDMA_UDA_CQPSQ_MG_IPV4VALID, info->ipv4_valid));
print_hex_dump_debug("WQE: MANAGE_MCG WQE" , DUMP_PREFIX_OFFSET, 16 , 8 ,
wqe, IRDMA_CQP_WQE_SIZE * 8 , false );
print_hex_dump_debug("WQE: MCG_HOST CTX WQE" , DUMP_PREFIX_OFFSET, 16 ,
8 , info->dma_mem_mc.va,
IRDMA_MAX_MGS_PER_CTX * 8 , false );
irdma_sc_cqp_post_sq(cqp);
return 0 ;
}
/**
* irdma_compare_mgs - Compares two multicast group structures
* @ entry1 : Multcast group info
* @ entry2 : Multcast group info in context
*/
static bool irdma_compare_mgs(struct irdma_mcast_grp_ctx_entry_info *entry1,
struct irdma_mcast_grp_ctx_entry_info *entry2)
{
if (entry1->dest_port == entry2->dest_port &&
entry1->qp_id == entry2->qp_id)
return true ;
return false ;
}
/**
* irdma_sc_add_mcast_grp - Allocates mcast group entry in ctx
* @ ctx : Multcast group context
* @ mg : Multcast group info
*/
int irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx,
struct irdma_mcast_grp_ctx_entry_info *mg)
{
u32 idx;
bool free_entry_found = false ;
u32 free_entry_idx = 0 ;
/* find either an identical or a free entry for a multicast group */
for (idx = 0 ; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
if (ctx->mg_ctx_info[idx].valid_entry) {
if (irdma_compare_mgs(&ctx->mg_ctx_info[idx], mg)) {
ctx->mg_ctx_info[idx].use_cnt++;
return 0 ;
}
continue ;
}
if (!free_entry_found) {
free_entry_found = true ;
free_entry_idx = idx;
}
}
if (free_entry_found) {
ctx->mg_ctx_info[free_entry_idx] = *mg;
ctx->mg_ctx_info[free_entry_idx].valid_entry = true ;
ctx->mg_ctx_info[free_entry_idx].use_cnt = 1 ;
ctx->no_of_mgs++;
return 0 ;
}
return -ENOMEM;
}
/**
* irdma_sc_del_mcast_grp - Delete mcast group
* @ ctx : Multcast group context
* @ mg : Multcast group info
*
* Finds and removes a specific mulicast group from context , all
* parameters must match to remove a multicast group .
*/
int irdma_sc_del_mcast_grp(struct irdma_mcast_grp_info *ctx,
struct irdma_mcast_grp_ctx_entry_info *mg)
{
u32 idx;
/* find an entry in multicast group context */
for (idx = 0 ; idx < IRDMA_MAX_MGS_PER_CTX; idx++) {
if (!ctx->mg_ctx_info[idx].valid_entry)
continue ;
if (irdma_compare_mgs(mg, &ctx->mg_ctx_info[idx])) {
ctx->mg_ctx_info[idx].use_cnt--;
if (!ctx->mg_ctx_info[idx].use_cnt) {
ctx->mg_ctx_info[idx].valid_entry = false ;
ctx->no_of_mgs--;
/* Remove gap if element was not the last */
if (idx != ctx->no_of_mgs &&
ctx->no_of_mgs > 0 ) {
memcpy(&ctx->mg_ctx_info[idx],
&ctx->mg_ctx_info[ctx->no_of_mgs - 1 ],
sizeof (ctx->mg_ctx_info[idx]));
ctx->mg_ctx_info[ctx->no_of_mgs - 1 ].valid_entry = false ;
}
}
return 0 ;
}
}
return -EINVAL;
}
Messung V0.5 in Prozent C=92 H=96 G=93
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland