| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- // 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;
- }
|