/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2014-2018 Broadcom * All rights reserved. */ #include #include #include #include #include #include #include #include "bnxt.h" #include "bnxt_filter.h" #include "bnxt_hwrm.h" #include "bnxt_vnic.h" #include "hsi_struct_def_dpdk.h" /* * Filter Functions */ struct bnxt_filter_info *bnxt_alloc_filter(struct bnxt *bp) { struct bnxt_filter_info *filter; /* Find the 1st unused filter from the free_filter_list pool*/ filter = STAILQ_FIRST(&bp->free_filter_list); if (!filter) { PMD_DRV_LOG(ERR, "No more free filter resources\n"); return NULL; } STAILQ_REMOVE_HEAD(&bp->free_filter_list, next); /* Default to L2 MAC Addr filter */ filter->flags = HWRM_CFA_L2_FILTER_ALLOC_INPUT_FLAGS_PATH_RX; filter->enables = HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR | HWRM_CFA_L2_FILTER_ALLOC_INPUT_ENABLES_L2_ADDR_MASK; memcpy(filter->l2_addr, bp->eth_dev->data->mac_addrs->addr_bytes, ETHER_ADDR_LEN); memset(filter->l2_addr_mask, 0xff, ETHER_ADDR_LEN); return filter; } struct bnxt_filter_info *bnxt_alloc_vf_filter(struct bnxt *bp, uint16_t vf) { struct bnxt_filter_info *filter; filter = rte_zmalloc("bnxt_vf_filter_info", sizeof(*filter), 0); if (!filter) { PMD_DRV_LOG(ERR, "Failed to alloc memory for VF %hu filters\n", vf); return NULL; } filter->fw_l2_filter_id = UINT64_MAX; STAILQ_INSERT_TAIL(&bp->pf.vf_info[vf].filter, filter, next); return filter; } void bnxt_init_filters(struct bnxt *bp) { struct bnxt_filter_info *filter; int i, max_filters; max_filters = bp->max_l2_ctx; STAILQ_INIT(&bp->free_filter_list); for (i = 0; i < max_filters; i++) { filter = &bp->filter_info[i]; filter->fw_l2_filter_id = UINT64_MAX; filter->fw_em_filter_id = UINT64_MAX; filter->fw_ntuple_filter_id = UINT64_MAX; STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); } } void bnxt_free_all_filters(struct bnxt *bp) { struct bnxt_vnic_info *vnic; struct bnxt_filter_info *filter, *temp_filter; unsigned int i; // for (i = 0; i < MAX_FF_POOLS; i++) { for (i = 0; i < bp->nr_vnics; i++) { vnic = &bp->vnic_info[i]; filter = STAILQ_FIRST(&vnic->filter); while (filter) { temp_filter = STAILQ_NEXT(filter, next); STAILQ_REMOVE(&vnic->filter, filter, bnxt_filter_info, next); STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); filter = temp_filter; } STAILQ_INIT(&vnic->filter); } for (i = 0; i < bp->pf.max_vfs; i++) { STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) { bnxt_hwrm_clear_l2_filter(bp, filter); } } } void bnxt_free_filter_mem(struct bnxt *bp) { struct bnxt_filter_info *filter; uint16_t max_filters, i; int rc = 0; if (bp->filter_info == NULL) return; /* Ensure that all filters are freed */ max_filters = bp->max_l2_ctx; for (i = 0; i < max_filters; i++) { filter = &bp->filter_info[i]; if (filter->fw_l2_filter_id != ((uint64_t)-1) && filter->filter_type == HWRM_CFA_L2_FILTER) { PMD_DRV_LOG(ERR, "L2 filter is not free\n"); /* Call HWRM to try to free filter again */ rc = bnxt_hwrm_clear_l2_filter(bp, filter); if (rc) PMD_DRV_LOG(ERR, "Cannot free L2 filter: %d\n", rc); } filter->fw_l2_filter_id = UINT64_MAX; if (filter->fw_ntuple_filter_id != ((uint64_t)-1) && filter->filter_type == HWRM_CFA_NTUPLE_FILTER) { PMD_DRV_LOG(ERR, "NTUPLE filter is not free\n"); /* Call HWRM to try to free filter again */ rc = bnxt_hwrm_clear_ntuple_filter(bp, filter); if (rc) PMD_DRV_LOG(ERR, "Cannot free NTUPLE filter: %d\n", rc); } filter->fw_ntuple_filter_id = UINT64_MAX; } STAILQ_INIT(&bp->free_filter_list); rte_free(bp->filter_info); bp->filter_info = NULL; for (i = 0; i < bp->pf.max_vfs; i++) { STAILQ_FOREACH(filter, &bp->pf.vf_info[i].filter, next) { rte_free(filter); STAILQ_REMOVE(&bp->pf.vf_info[i].filter, filter, bnxt_filter_info, next); } } } int bnxt_alloc_filter_mem(struct bnxt *bp) { struct bnxt_filter_info *filter_mem; uint16_t max_filters; max_filters = bp->max_l2_ctx; /* Allocate memory for VNIC pool and filter pool */ filter_mem = rte_zmalloc("bnxt_filter_info", max_filters * sizeof(struct bnxt_filter_info), 0); if (filter_mem == NULL) { PMD_DRV_LOG(ERR, "Failed to alloc memory for %d filters", max_filters); return -ENOMEM; } bp->filter_info = filter_mem; return 0; } struct bnxt_filter_info *bnxt_get_unused_filter(struct bnxt *bp) { struct bnxt_filter_info *filter; /* Find the 1st unused filter from the free_filter_list pool*/ filter = STAILQ_FIRST(&bp->free_filter_list); if (!filter) { PMD_DRV_LOG(ERR, "No more free filter resources\n"); return NULL; } STAILQ_REMOVE_HEAD(&bp->free_filter_list, next); return filter; } void bnxt_free_filter(struct bnxt *bp, struct bnxt_filter_info *filter) { STAILQ_INSERT_TAIL(&bp->free_filter_list, filter, next); }