18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) 28c2ecf20Sopenharmony_ci/* QLogic qed NIC Driver 38c2ecf20Sopenharmony_ci * Copyright (c) 2015-2017 QLogic Corporation 48c2ecf20Sopenharmony_ci * Copyright (c) 2019-2020 Marvell International Ltd. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/types.h> 88c2ecf20Sopenharmony_ci#include <asm/byteorder.h> 98c2ecf20Sopenharmony_ci#include <asm/param.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 128c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/kernel.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/pci.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/stddef.h> 198c2ecf20Sopenharmony_ci#include <linux/string.h> 208c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 218c2ecf20Sopenharmony_ci#include <linux/bitops.h> 228c2ecf20Sopenharmony_ci#include <linux/bug.h> 238c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 248c2ecf20Sopenharmony_ci#include "qed.h" 258c2ecf20Sopenharmony_ci#include <linux/qed/qed_chain.h> 268c2ecf20Sopenharmony_ci#include "qed_cxt.h" 278c2ecf20Sopenharmony_ci#include "qed_dcbx.h" 288c2ecf20Sopenharmony_ci#include "qed_dev_api.h" 298c2ecf20Sopenharmony_ci#include <linux/qed/qed_eth_if.h> 308c2ecf20Sopenharmony_ci#include "qed_hsi.h" 318c2ecf20Sopenharmony_ci#include "qed_hw.h" 328c2ecf20Sopenharmony_ci#include "qed_int.h" 338c2ecf20Sopenharmony_ci#include "qed_l2.h" 348c2ecf20Sopenharmony_ci#include "qed_mcp.h" 358c2ecf20Sopenharmony_ci#include "qed_ptp.h" 368c2ecf20Sopenharmony_ci#include "qed_reg_addr.h" 378c2ecf20Sopenharmony_ci#include "qed_sp.h" 388c2ecf20Sopenharmony_ci#include "qed_sriov.h" 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define QED_MAX_SGES_NUM 16 428c2ecf20Sopenharmony_ci#define CRC32_POLY 0x1edc6f41 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistruct qed_l2_info { 458c2ecf20Sopenharmony_ci u32 queues; 468c2ecf20Sopenharmony_ci unsigned long **pp_qid_usage; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* The lock is meant to synchronize access to the qid usage */ 498c2ecf20Sopenharmony_ci struct mutex lock; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint qed_l2_alloc(struct qed_hwfn *p_hwfn) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct qed_l2_info *p_l2_info; 558c2ecf20Sopenharmony_ci unsigned long **pp_qids; 568c2ecf20Sopenharmony_ci u32 i; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (!QED_IS_L2_PERSONALITY(p_hwfn)) 598c2ecf20Sopenharmony_ci return 0; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci p_l2_info = kzalloc(sizeof(*p_l2_info), GFP_KERNEL); 628c2ecf20Sopenharmony_ci if (!p_l2_info) 638c2ecf20Sopenharmony_ci return -ENOMEM; 648c2ecf20Sopenharmony_ci p_hwfn->p_l2_info = p_l2_info; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 678c2ecf20Sopenharmony_ci p_l2_info->queues = RESC_NUM(p_hwfn, QED_L2_QUEUE); 688c2ecf20Sopenharmony_ci } else { 698c2ecf20Sopenharmony_ci u8 rx = 0, tx = 0; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci qed_vf_get_num_rxqs(p_hwfn, &rx); 728c2ecf20Sopenharmony_ci qed_vf_get_num_txqs(p_hwfn, &tx); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci p_l2_info->queues = max_t(u8, rx, tx); 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci pp_qids = kcalloc(p_l2_info->queues, sizeof(unsigned long *), 788c2ecf20Sopenharmony_ci GFP_KERNEL); 798c2ecf20Sopenharmony_ci if (!pp_qids) 808c2ecf20Sopenharmony_ci return -ENOMEM; 818c2ecf20Sopenharmony_ci p_l2_info->pp_qid_usage = pp_qids; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci for (i = 0; i < p_l2_info->queues; i++) { 848c2ecf20Sopenharmony_ci pp_qids[i] = kzalloc(MAX_QUEUES_PER_QZONE / 8, GFP_KERNEL); 858c2ecf20Sopenharmony_ci if (!pp_qids[i]) 868c2ecf20Sopenharmony_ci return -ENOMEM; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci return 0; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_civoid qed_l2_setup(struct qed_hwfn *p_hwfn) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci if (!QED_IS_L2_PERSONALITY(p_hwfn)) 958c2ecf20Sopenharmony_ci return; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci mutex_init(&p_hwfn->p_l2_info->lock); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_civoid qed_l2_free(struct qed_hwfn *p_hwfn) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci u32 i; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci if (!QED_IS_L2_PERSONALITY(p_hwfn)) 1058c2ecf20Sopenharmony_ci return; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (!p_hwfn->p_l2_info) 1088c2ecf20Sopenharmony_ci return; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (!p_hwfn->p_l2_info->pp_qid_usage) 1118c2ecf20Sopenharmony_ci goto out_l2_info; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci /* Free until hit first uninitialized entry */ 1148c2ecf20Sopenharmony_ci for (i = 0; i < p_hwfn->p_l2_info->queues; i++) { 1158c2ecf20Sopenharmony_ci if (!p_hwfn->p_l2_info->pp_qid_usage[i]) 1168c2ecf20Sopenharmony_ci break; 1178c2ecf20Sopenharmony_ci kfree(p_hwfn->p_l2_info->pp_qid_usage[i]); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci kfree(p_hwfn->p_l2_info->pp_qid_usage); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ciout_l2_info: 1238c2ecf20Sopenharmony_ci kfree(p_hwfn->p_l2_info); 1248c2ecf20Sopenharmony_ci p_hwfn->p_l2_info = NULL; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic bool qed_eth_queue_qid_usage_add(struct qed_hwfn *p_hwfn, 1288c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci struct qed_l2_info *p_l2_info = p_hwfn->p_l2_info; 1318c2ecf20Sopenharmony_ci u16 queue_id = p_cid->rel.queue_id; 1328c2ecf20Sopenharmony_ci bool b_rc = true; 1338c2ecf20Sopenharmony_ci u8 first; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci mutex_lock(&p_l2_info->lock); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (queue_id >= p_l2_info->queues) { 1388c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 1398c2ecf20Sopenharmony_ci "Requested to increase usage for qzone %04x out of %08x\n", 1408c2ecf20Sopenharmony_ci queue_id, p_l2_info->queues); 1418c2ecf20Sopenharmony_ci b_rc = false; 1428c2ecf20Sopenharmony_ci goto out; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci first = (u8)find_first_zero_bit(p_l2_info->pp_qid_usage[queue_id], 1468c2ecf20Sopenharmony_ci MAX_QUEUES_PER_QZONE); 1478c2ecf20Sopenharmony_ci if (first >= MAX_QUEUES_PER_QZONE) { 1488c2ecf20Sopenharmony_ci b_rc = false; 1498c2ecf20Sopenharmony_ci goto out; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci __set_bit(first, p_l2_info->pp_qid_usage[queue_id]); 1538c2ecf20Sopenharmony_ci p_cid->qid_usage_idx = first; 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ciout: 1568c2ecf20Sopenharmony_ci mutex_unlock(&p_l2_info->lock); 1578c2ecf20Sopenharmony_ci return b_rc; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic void qed_eth_queue_qid_usage_del(struct qed_hwfn *p_hwfn, 1618c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci mutex_lock(&p_hwfn->p_l2_info->lock); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci clear_bit(p_cid->qid_usage_idx, 1668c2ecf20Sopenharmony_ci p_hwfn->p_l2_info->pp_qid_usage[p_cid->rel.queue_id]); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci mutex_unlock(&p_hwfn->p_l2_info->lock); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_civoid qed_eth_queue_cid_release(struct qed_hwfn *p_hwfn, 1728c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci bool b_legacy_vf = !!(p_cid->vf_legacy & QED_QCID_LEGACY_VF_CID); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev) && !b_legacy_vf) 1778c2ecf20Sopenharmony_ci _qed_cxt_release_cid(p_hwfn, p_cid->cid, p_cid->vfid); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci /* For PF's VFs we maintain the index inside queue-zone in IOV */ 1808c2ecf20Sopenharmony_ci if (p_cid->vfid == QED_QUEUE_CID_SELF) 1818c2ecf20Sopenharmony_ci qed_eth_queue_qid_usage_del(p_hwfn, p_cid); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci vfree(p_cid); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci/* The internal is only meant to be directly called by PFs initializeing CIDs 1878c2ecf20Sopenharmony_ci * for their VFs. 1888c2ecf20Sopenharmony_ci */ 1898c2ecf20Sopenharmony_cistatic struct qed_queue_cid * 1908c2ecf20Sopenharmony_ci_qed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, 1918c2ecf20Sopenharmony_ci u16 opaque_fid, 1928c2ecf20Sopenharmony_ci u32 cid, 1938c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 1948c2ecf20Sopenharmony_ci bool b_is_rx, 1958c2ecf20Sopenharmony_ci struct qed_queue_cid_vf_params *p_vf_params) 1968c2ecf20Sopenharmony_ci{ 1978c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid; 1988c2ecf20Sopenharmony_ci int rc; 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci p_cid = vzalloc(sizeof(*p_cid)); 2018c2ecf20Sopenharmony_ci if (!p_cid) 2028c2ecf20Sopenharmony_ci return NULL; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci p_cid->opaque_fid = opaque_fid; 2058c2ecf20Sopenharmony_ci p_cid->cid = cid; 2068c2ecf20Sopenharmony_ci p_cid->p_owner = p_hwfn; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* Fill in parameters */ 2098c2ecf20Sopenharmony_ci p_cid->rel.vport_id = p_params->vport_id; 2108c2ecf20Sopenharmony_ci p_cid->rel.queue_id = p_params->queue_id; 2118c2ecf20Sopenharmony_ci p_cid->rel.stats_id = p_params->stats_id; 2128c2ecf20Sopenharmony_ci p_cid->sb_igu_id = p_params->p_sb->igu_sb_id; 2138c2ecf20Sopenharmony_ci p_cid->b_is_rx = b_is_rx; 2148c2ecf20Sopenharmony_ci p_cid->sb_idx = p_params->sb_idx; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* Fill-in bits related to VFs' queues if information was provided */ 2178c2ecf20Sopenharmony_ci if (p_vf_params) { 2188c2ecf20Sopenharmony_ci p_cid->vfid = p_vf_params->vfid; 2198c2ecf20Sopenharmony_ci p_cid->vf_qid = p_vf_params->vf_qid; 2208c2ecf20Sopenharmony_ci p_cid->vf_legacy = p_vf_params->vf_legacy; 2218c2ecf20Sopenharmony_ci } else { 2228c2ecf20Sopenharmony_ci p_cid->vfid = QED_QUEUE_CID_SELF; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* Don't try calculating the absolute indices for VFs */ 2268c2ecf20Sopenharmony_ci if (IS_VF(p_hwfn->cdev)) { 2278c2ecf20Sopenharmony_ci p_cid->abs = p_cid->rel; 2288c2ecf20Sopenharmony_ci goto out; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* Calculate the engine-absolute indices of the resources. 2328c2ecf20Sopenharmony_ci * This would guarantee they're valid later on. 2338c2ecf20Sopenharmony_ci * In some cases [SBs] we already have the right values. 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_cid->rel.vport_id, &p_cid->abs.vport_id); 2368c2ecf20Sopenharmony_ci if (rc) 2378c2ecf20Sopenharmony_ci goto fail; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci rc = qed_fw_l2_queue(p_hwfn, p_cid->rel.queue_id, &p_cid->abs.queue_id); 2408c2ecf20Sopenharmony_ci if (rc) 2418c2ecf20Sopenharmony_ci goto fail; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /* In case of a PF configuring its VF's queues, the stats-id is already 2448c2ecf20Sopenharmony_ci * absolute [since there's a single index that's suitable per-VF]. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci if (p_cid->vfid == QED_QUEUE_CID_SELF) { 2478c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_cid->rel.stats_id, 2488c2ecf20Sopenharmony_ci &p_cid->abs.stats_id); 2498c2ecf20Sopenharmony_ci if (rc) 2508c2ecf20Sopenharmony_ci goto fail; 2518c2ecf20Sopenharmony_ci } else { 2528c2ecf20Sopenharmony_ci p_cid->abs.stats_id = p_cid->rel.stats_id; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ciout: 2568c2ecf20Sopenharmony_ci /* VF-images have provided the qid_usage_idx on their own. 2578c2ecf20Sopenharmony_ci * Otherwise, we need to allocate a unique one. 2588c2ecf20Sopenharmony_ci */ 2598c2ecf20Sopenharmony_ci if (!p_vf_params) { 2608c2ecf20Sopenharmony_ci if (!qed_eth_queue_qid_usage_add(p_hwfn, p_cid)) 2618c2ecf20Sopenharmony_ci goto fail; 2628c2ecf20Sopenharmony_ci } else { 2638c2ecf20Sopenharmony_ci p_cid->qid_usage_idx = p_vf_params->qid_usage_idx; 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, 2678c2ecf20Sopenharmony_ci QED_MSG_SP, 2688c2ecf20Sopenharmony_ci "opaque_fid: %04x CID %08x vport %02x [%02x] qzone %04x.%02x [%04x] stats %02x [%02x] SB %04x PI %02x\n", 2698c2ecf20Sopenharmony_ci p_cid->opaque_fid, 2708c2ecf20Sopenharmony_ci p_cid->cid, 2718c2ecf20Sopenharmony_ci p_cid->rel.vport_id, 2728c2ecf20Sopenharmony_ci p_cid->abs.vport_id, 2738c2ecf20Sopenharmony_ci p_cid->rel.queue_id, 2748c2ecf20Sopenharmony_ci p_cid->qid_usage_idx, 2758c2ecf20Sopenharmony_ci p_cid->abs.queue_id, 2768c2ecf20Sopenharmony_ci p_cid->rel.stats_id, 2778c2ecf20Sopenharmony_ci p_cid->abs.stats_id, p_cid->sb_igu_id, p_cid->sb_idx); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return p_cid; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_cifail: 2828c2ecf20Sopenharmony_ci vfree(p_cid); 2838c2ecf20Sopenharmony_ci return NULL; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistruct qed_queue_cid * 2878c2ecf20Sopenharmony_ciqed_eth_queue_to_cid(struct qed_hwfn *p_hwfn, 2888c2ecf20Sopenharmony_ci u16 opaque_fid, 2898c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 2908c2ecf20Sopenharmony_ci bool b_is_rx, 2918c2ecf20Sopenharmony_ci struct qed_queue_cid_vf_params *p_vf_params) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid; 2948c2ecf20Sopenharmony_ci u8 vfid = QED_CXT_PF_CID; 2958c2ecf20Sopenharmony_ci bool b_legacy_vf = false; 2968c2ecf20Sopenharmony_ci u32 cid = 0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci /* In case of legacy VFs, The CID can be derived from the additional 2998c2ecf20Sopenharmony_ci * VF parameters - the VF assumes queue X uses CID X, so we can simply 3008c2ecf20Sopenharmony_ci * use the vf_qid for this purpose as well. 3018c2ecf20Sopenharmony_ci */ 3028c2ecf20Sopenharmony_ci if (p_vf_params) { 3038c2ecf20Sopenharmony_ci vfid = p_vf_params->vfid; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci if (p_vf_params->vf_legacy & QED_QCID_LEGACY_VF_CID) { 3068c2ecf20Sopenharmony_ci b_legacy_vf = true; 3078c2ecf20Sopenharmony_ci cid = p_vf_params->vf_qid; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* Get a unique firmware CID for this queue, in case it's a PF. 3128c2ecf20Sopenharmony_ci * VF's don't need a CID as the queue configuration will be done 3138c2ecf20Sopenharmony_ci * by PF. 3148c2ecf20Sopenharmony_ci */ 3158c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev) && !b_legacy_vf) { 3168c2ecf20Sopenharmony_ci if (_qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_ETH, 3178c2ecf20Sopenharmony_ci &cid, vfid)) { 3188c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "Failed to acquire cid\n"); 3198c2ecf20Sopenharmony_ci return NULL; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci p_cid = _qed_eth_queue_to_cid(p_hwfn, opaque_fid, cid, 3248c2ecf20Sopenharmony_ci p_params, b_is_rx, p_vf_params); 3258c2ecf20Sopenharmony_ci if (!p_cid && IS_PF(p_hwfn->cdev) && !b_legacy_vf) 3268c2ecf20Sopenharmony_ci _qed_cxt_release_cid(p_hwfn, cid, vfid); 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci return p_cid; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic struct qed_queue_cid * 3328c2ecf20Sopenharmony_ciqed_eth_queue_to_cid_pf(struct qed_hwfn *p_hwfn, 3338c2ecf20Sopenharmony_ci u16 opaque_fid, 3348c2ecf20Sopenharmony_ci bool b_is_rx, 3358c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci return qed_eth_queue_to_cid(p_hwfn, opaque_fid, p_params, b_is_rx, 3388c2ecf20Sopenharmony_ci NULL); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ciint qed_sp_eth_vport_start(struct qed_hwfn *p_hwfn, 3428c2ecf20Sopenharmony_ci struct qed_sp_vport_start_params *p_params) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct vport_start_ramrod_data *p_ramrod = NULL; 3458c2ecf20Sopenharmony_ci struct eth_vport_tpa_param *tpa_param; 3468c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 3478c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 3488c2ecf20Sopenharmony_ci u16 min_size, rx_mode = 0; 3498c2ecf20Sopenharmony_ci u8 abs_vport_id = 0; 3508c2ecf20Sopenharmony_ci int rc; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); 3538c2ecf20Sopenharmony_ci if (rc) 3548c2ecf20Sopenharmony_ci return rc; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 3578c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 3588c2ecf20Sopenharmony_ci init_data.opaque_fid = p_params->opaque_fid; 3598c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 3628c2ecf20Sopenharmony_ci ETH_RAMROD_VPORT_START, 3638c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 3648c2ecf20Sopenharmony_ci if (rc) 3658c2ecf20Sopenharmony_ci return rc; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.vport_start; 3688c2ecf20Sopenharmony_ci p_ramrod->vport_id = abs_vport_id; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci p_ramrod->mtu = cpu_to_le16(p_params->mtu); 3718c2ecf20Sopenharmony_ci p_ramrod->handle_ptp_pkts = p_params->handle_ptp_pkts; 3728c2ecf20Sopenharmony_ci p_ramrod->inner_vlan_removal_en = p_params->remove_inner_vlan; 3738c2ecf20Sopenharmony_ci p_ramrod->drop_ttl0_en = p_params->drop_ttl0; 3748c2ecf20Sopenharmony_ci p_ramrod->untagged = p_params->only_untagged; 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1); 3778c2ecf20Sopenharmony_ci SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci p_ramrod->rx_mode.state = cpu_to_le16(rx_mode); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci /* TPA related fields */ 3828c2ecf20Sopenharmony_ci tpa_param = &p_ramrod->tpa_param; 3838c2ecf20Sopenharmony_ci memset(tpa_param, 0, sizeof(*tpa_param)); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci tpa_param->max_buff_num = p_params->max_buffers_per_cqe; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci switch (p_params->tpa_mode) { 3888c2ecf20Sopenharmony_ci case QED_TPA_MODE_GRO: 3898c2ecf20Sopenharmony_ci min_size = p_params->mtu / 2; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci tpa_param->tpa_max_aggs_num = ETH_TPA_MAX_AGGS_NUM; 3928c2ecf20Sopenharmony_ci tpa_param->tpa_max_size = cpu_to_le16(U16_MAX); 3938c2ecf20Sopenharmony_ci tpa_param->tpa_min_size_to_cont = cpu_to_le16(min_size); 3948c2ecf20Sopenharmony_ci tpa_param->tpa_min_size_to_start = cpu_to_le16(min_size); 3958c2ecf20Sopenharmony_ci tpa_param->tpa_ipv4_en_flg = 1; 3968c2ecf20Sopenharmony_ci tpa_param->tpa_ipv6_en_flg = 1; 3978c2ecf20Sopenharmony_ci tpa_param->tpa_pkt_split_flg = 1; 3988c2ecf20Sopenharmony_ci tpa_param->tpa_gro_consistent_flg = 1; 3998c2ecf20Sopenharmony_ci default: 4008c2ecf20Sopenharmony_ci break; 4018c2ecf20Sopenharmony_ci } 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_ci p_ramrod->tx_switching_en = p_params->tx_switching; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci p_ramrod->ctl_frame_mac_check_en = !!p_params->check_mac; 4068c2ecf20Sopenharmony_ci p_ramrod->ctl_frame_ethtype_check_en = !!p_params->check_ethtype; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci /* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */ 4098c2ecf20Sopenharmony_ci p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev, 4108c2ecf20Sopenharmony_ci p_params->concrete_fid); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic int qed_sp_vport_start(struct qed_hwfn *p_hwfn, 4168c2ecf20Sopenharmony_ci struct qed_sp_vport_start_params *p_params) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci if (IS_VF(p_hwfn->cdev)) { 4198c2ecf20Sopenharmony_ci return qed_vf_pf_vport_start(p_hwfn, p_params->vport_id, 4208c2ecf20Sopenharmony_ci p_params->mtu, 4218c2ecf20Sopenharmony_ci p_params->remove_inner_vlan, 4228c2ecf20Sopenharmony_ci p_params->tpa_mode, 4238c2ecf20Sopenharmony_ci p_params->max_buffers_per_cqe, 4248c2ecf20Sopenharmony_ci p_params->only_untagged); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return qed_sp_eth_vport_start(p_hwfn, p_params); 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int 4318c2ecf20Sopenharmony_ciqed_sp_vport_update_rss(struct qed_hwfn *p_hwfn, 4328c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod, 4338c2ecf20Sopenharmony_ci struct qed_rss_params *p_rss) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci struct eth_vport_rss_config *p_config; 4368c2ecf20Sopenharmony_ci u16 capabilities = 0; 4378c2ecf20Sopenharmony_ci int i, table_size; 4388c2ecf20Sopenharmony_ci int rc = 0; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci if (!p_rss) { 4418c2ecf20Sopenharmony_ci p_ramrod->common.update_rss_flg = 0; 4428c2ecf20Sopenharmony_ci return rc; 4438c2ecf20Sopenharmony_ci } 4448c2ecf20Sopenharmony_ci p_config = &p_ramrod->rss_config; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci BUILD_BUG_ON(QED_RSS_IND_TABLE_SIZE != ETH_RSS_IND_TABLE_ENTRIES_NUM); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci rc = qed_fw_rss_eng(p_hwfn, p_rss->rss_eng_id, &p_config->rss_id); 4498c2ecf20Sopenharmony_ci if (rc) 4508c2ecf20Sopenharmony_ci return rc; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci p_ramrod->common.update_rss_flg = p_rss->update_rss_config; 4538c2ecf20Sopenharmony_ci p_config->update_rss_capabilities = p_rss->update_rss_capabilities; 4548c2ecf20Sopenharmony_ci p_config->update_rss_ind_table = p_rss->update_rss_ind_table; 4558c2ecf20Sopenharmony_ci p_config->update_rss_key = p_rss->update_rss_key; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci p_config->rss_mode = p_rss->rss_enable ? 4588c2ecf20Sopenharmony_ci ETH_VPORT_RSS_MODE_REGULAR : 4598c2ecf20Sopenharmony_ci ETH_VPORT_RSS_MODE_DISABLED; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4628c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY, 4638c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV4)); 4648c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4658c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY, 4668c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV6)); 4678c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4688c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY, 4698c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV4_TCP)); 4708c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4718c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY, 4728c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV6_TCP)); 4738c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4748c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY, 4758c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV4_UDP)); 4768c2ecf20Sopenharmony_ci SET_FIELD(capabilities, 4778c2ecf20Sopenharmony_ci ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY, 4788c2ecf20Sopenharmony_ci !!(p_rss->rss_caps & QED_RSS_IPV6_UDP)); 4798c2ecf20Sopenharmony_ci p_config->tbl_size = p_rss->rss_table_size_log; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci p_config->capabilities = cpu_to_le16(capabilities); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 4848c2ecf20Sopenharmony_ci "update rss flag %d, rss_mode = %d, update_caps = %d, capabilities = %d, update_ind = %d, update_rss_key = %d\n", 4858c2ecf20Sopenharmony_ci p_ramrod->common.update_rss_flg, 4868c2ecf20Sopenharmony_ci p_config->rss_mode, 4878c2ecf20Sopenharmony_ci p_config->update_rss_capabilities, 4888c2ecf20Sopenharmony_ci p_config->capabilities, 4898c2ecf20Sopenharmony_ci p_config->update_rss_ind_table, p_config->update_rss_key); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci table_size = min_t(int, QED_RSS_IND_TABLE_SIZE, 4928c2ecf20Sopenharmony_ci 1 << p_config->tbl_size); 4938c2ecf20Sopenharmony_ci for (i = 0; i < table_size; i++) { 4948c2ecf20Sopenharmony_ci struct qed_queue_cid *p_queue = p_rss->rss_ind_table[i]; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (!p_queue) 4978c2ecf20Sopenharmony_ci return -EINVAL; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci p_config->indirection_table[i] = 5008c2ecf20Sopenharmony_ci cpu_to_le16(p_queue->abs.queue_id); 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, NETIF_MSG_IFUP, 5048c2ecf20Sopenharmony_ci "Configured RSS indirection table [%d entries]:\n", 5058c2ecf20Sopenharmony_ci table_size); 5068c2ecf20Sopenharmony_ci for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i += 0x10) { 5078c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, 5088c2ecf20Sopenharmony_ci NETIF_MSG_IFUP, 5098c2ecf20Sopenharmony_ci "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", 5108c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i]), 5118c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 1]), 5128c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 2]), 5138c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 3]), 5148c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 4]), 5158c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 5]), 5168c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 6]), 5178c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 7]), 5188c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 8]), 5198c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 9]), 5208c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 10]), 5218c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 11]), 5228c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 12]), 5238c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 13]), 5248c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 14]), 5258c2ecf20Sopenharmony_ci le16_to_cpu(p_config->indirection_table[i + 15])); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci for (i = 0; i < 10; i++) 5298c2ecf20Sopenharmony_ci p_config->rss_key[i] = cpu_to_le32(p_rss->rss_key[i]); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci return rc; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic void 5358c2ecf20Sopenharmony_ciqed_sp_update_accept_mode(struct qed_hwfn *p_hwfn, 5368c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod, 5378c2ecf20Sopenharmony_ci struct qed_filter_accept_flags accept_flags) 5388c2ecf20Sopenharmony_ci{ 5398c2ecf20Sopenharmony_ci p_ramrod->common.update_rx_mode_flg = 5408c2ecf20Sopenharmony_ci accept_flags.update_rx_mode_config; 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_ci p_ramrod->common.update_tx_mode_flg = 5438c2ecf20Sopenharmony_ci accept_flags.update_tx_mode_config; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci /* Set Rx mode accept flags */ 5468c2ecf20Sopenharmony_ci if (p_ramrod->common.update_rx_mode_flg) { 5478c2ecf20Sopenharmony_ci u8 accept_filter = accept_flags.rx_accept_filter; 5488c2ecf20Sopenharmony_ci u16 state = 0; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 5518c2ecf20Sopenharmony_ci !(!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) || 5528c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED))); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_UCAST_ACCEPT_UNMATCHED, 5558c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)); 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 5588c2ecf20Sopenharmony_ci !(!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) || 5598c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_MCAST_ACCEPT_ALL, 5628c2ecf20Sopenharmony_ci (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) && 5638c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL, 5668c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_BCAST)); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_RX_MODE_ACCEPT_ANY_VNI, 5698c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_ANY_VNI)); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci p_ramrod->rx_mode.state = cpu_to_le16(state); 5728c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 5738c2ecf20Sopenharmony_ci "p_ramrod->rx_mode.state = 0x%x\n", state); 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci /* Set Tx mode accept flags */ 5778c2ecf20Sopenharmony_ci if (p_ramrod->common.update_tx_mode_flg) { 5788c2ecf20Sopenharmony_ci u8 accept_filter = accept_flags.tx_accept_filter; 5798c2ecf20Sopenharmony_ci u16 state = 0; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_DROP_ALL, 5828c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_NONE)); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_TX_MODE_MCAST_DROP_ALL, 5858c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_NONE)); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_TX_MODE_MCAST_ACCEPT_ALL, 5888c2ecf20Sopenharmony_ci (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) && 5898c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED))); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL, 5928c2ecf20Sopenharmony_ci (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) && 5938c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED))); 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL, 5968c2ecf20Sopenharmony_ci !!(accept_filter & QED_ACCEPT_BCAST)); 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci p_ramrod->tx_mode.state = cpu_to_le16(state); 5998c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 6008c2ecf20Sopenharmony_ci "p_ramrod->tx_mode.state = 0x%x\n", state); 6018c2ecf20Sopenharmony_ci } 6028c2ecf20Sopenharmony_ci} 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_cistatic void 6058c2ecf20Sopenharmony_ciqed_sp_vport_update_sge_tpa(struct qed_hwfn *p_hwfn, 6068c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod, 6078c2ecf20Sopenharmony_ci const struct qed_sge_tpa_params *param) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci struct eth_vport_tpa_param *tpa; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci if (!param) { 6128c2ecf20Sopenharmony_ci p_ramrod->common.update_tpa_param_flg = 0; 6138c2ecf20Sopenharmony_ci p_ramrod->common.update_tpa_en_flg = 0; 6148c2ecf20Sopenharmony_ci p_ramrod->common.update_tpa_param_flg = 0; 6158c2ecf20Sopenharmony_ci return; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci p_ramrod->common.update_tpa_en_flg = param->update_tpa_en_flg; 6198c2ecf20Sopenharmony_ci tpa = &p_ramrod->tpa_param; 6208c2ecf20Sopenharmony_ci tpa->tpa_ipv4_en_flg = param->tpa_ipv4_en_flg; 6218c2ecf20Sopenharmony_ci tpa->tpa_ipv6_en_flg = param->tpa_ipv6_en_flg; 6228c2ecf20Sopenharmony_ci tpa->tpa_ipv4_tunn_en_flg = param->tpa_ipv4_tunn_en_flg; 6238c2ecf20Sopenharmony_ci tpa->tpa_ipv6_tunn_en_flg = param->tpa_ipv6_tunn_en_flg; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci p_ramrod->common.update_tpa_param_flg = param->update_tpa_param_flg; 6268c2ecf20Sopenharmony_ci tpa->max_buff_num = param->max_buffers_per_cqe; 6278c2ecf20Sopenharmony_ci tpa->tpa_pkt_split_flg = param->tpa_pkt_split_flg; 6288c2ecf20Sopenharmony_ci tpa->tpa_hdr_data_split_flg = param->tpa_hdr_data_split_flg; 6298c2ecf20Sopenharmony_ci tpa->tpa_gro_consistent_flg = param->tpa_gro_consistent_flg; 6308c2ecf20Sopenharmony_ci tpa->tpa_max_aggs_num = param->tpa_max_aggs_num; 6318c2ecf20Sopenharmony_ci tpa->tpa_max_size = cpu_to_le16(param->tpa_max_size); 6328c2ecf20Sopenharmony_ci tpa->tpa_min_size_to_start = cpu_to_le16(param->tpa_min_size_to_start); 6338c2ecf20Sopenharmony_ci tpa->tpa_min_size_to_cont = cpu_to_le16(param->tpa_min_size_to_cont); 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_cistatic void 6378c2ecf20Sopenharmony_ciqed_sp_update_mcast_bin(struct qed_hwfn *p_hwfn, 6388c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod, 6398c2ecf20Sopenharmony_ci struct qed_sp_vport_update_params *p_params) 6408c2ecf20Sopenharmony_ci{ 6418c2ecf20Sopenharmony_ci int i; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci memset(&p_ramrod->approx_mcast.bins, 0, 6448c2ecf20Sopenharmony_ci sizeof(p_ramrod->approx_mcast.bins)); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci if (!p_params->update_approx_mcast_flg) 6478c2ecf20Sopenharmony_ci return; 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci p_ramrod->common.update_approx_mcast_flg = 1; 6508c2ecf20Sopenharmony_ci for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { 6518c2ecf20Sopenharmony_ci u32 *p_bins = p_params->bins; 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci p_ramrod->approx_mcast.bins[i] = cpu_to_le32(p_bins[i]); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ciint qed_sp_vport_update(struct qed_hwfn *p_hwfn, 6588c2ecf20Sopenharmony_ci struct qed_sp_vport_update_params *p_params, 6598c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 6608c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci struct qed_rss_params *p_rss_params = p_params->rss_params; 6638c2ecf20Sopenharmony_ci struct vport_update_ramrod_data_cmn *p_cmn; 6648c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 6658c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod = NULL; 6668c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 6678c2ecf20Sopenharmony_ci u8 abs_vport_id = 0, val; 6688c2ecf20Sopenharmony_ci int rc = -EINVAL; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (IS_VF(p_hwfn->cdev)) { 6718c2ecf20Sopenharmony_ci rc = qed_vf_pf_vport_update(p_hwfn, p_params); 6728c2ecf20Sopenharmony_ci return rc; 6738c2ecf20Sopenharmony_ci } 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); 6768c2ecf20Sopenharmony_ci if (rc) 6778c2ecf20Sopenharmony_ci return rc; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 6808c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 6818c2ecf20Sopenharmony_ci init_data.opaque_fid = p_params->opaque_fid; 6828c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 6838c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_data; 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 6868c2ecf20Sopenharmony_ci ETH_RAMROD_VPORT_UPDATE, 6878c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 6888c2ecf20Sopenharmony_ci if (rc) 6898c2ecf20Sopenharmony_ci return rc; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci /* Copy input params to ramrod according to FW struct */ 6928c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.vport_update; 6938c2ecf20Sopenharmony_ci p_cmn = &p_ramrod->common; 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_ci p_cmn->vport_id = abs_vport_id; 6968c2ecf20Sopenharmony_ci p_cmn->rx_active_flg = p_params->vport_active_rx_flg; 6978c2ecf20Sopenharmony_ci p_cmn->update_rx_active_flg = p_params->update_vport_active_rx_flg; 6988c2ecf20Sopenharmony_ci p_cmn->tx_active_flg = p_params->vport_active_tx_flg; 6998c2ecf20Sopenharmony_ci p_cmn->update_tx_active_flg = p_params->update_vport_active_tx_flg; 7008c2ecf20Sopenharmony_ci p_cmn->accept_any_vlan = p_params->accept_any_vlan; 7018c2ecf20Sopenharmony_ci val = p_params->update_accept_any_vlan_flg; 7028c2ecf20Sopenharmony_ci p_cmn->update_accept_any_vlan_flg = val; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci p_cmn->inner_vlan_removal_en = p_params->inner_vlan_removal_flg; 7058c2ecf20Sopenharmony_ci val = p_params->update_inner_vlan_removal_flg; 7068c2ecf20Sopenharmony_ci p_cmn->update_inner_vlan_removal_en_flg = val; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci p_cmn->default_vlan_en = p_params->default_vlan_enable_flg; 7098c2ecf20Sopenharmony_ci val = p_params->update_default_vlan_enable_flg; 7108c2ecf20Sopenharmony_ci p_cmn->update_default_vlan_en_flg = val; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci p_cmn->default_vlan = cpu_to_le16(p_params->default_vlan); 7138c2ecf20Sopenharmony_ci p_cmn->update_default_vlan_flg = p_params->update_default_vlan_flg; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci p_cmn->silent_vlan_removal_en = p_params->silent_vlan_removal_flg; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci p_ramrod->common.tx_switching_en = p_params->tx_switching_flg; 7188c2ecf20Sopenharmony_ci p_cmn->update_tx_switching_en_flg = p_params->update_tx_switching_flg; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci p_cmn->anti_spoofing_en = p_params->anti_spoofing_en; 7218c2ecf20Sopenharmony_ci val = p_params->update_anti_spoofing_en_flg; 7228c2ecf20Sopenharmony_ci p_ramrod->common.update_anti_spoofing_en_flg = val; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params); 7258c2ecf20Sopenharmony_ci if (rc) { 7268c2ecf20Sopenharmony_ci qed_sp_destroy_request(p_hwfn, p_ent); 7278c2ecf20Sopenharmony_ci return rc; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci if (p_params->update_ctl_frame_check) { 7318c2ecf20Sopenharmony_ci p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en; 7328c2ecf20Sopenharmony_ci p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en; 7338c2ecf20Sopenharmony_ci } 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci /* Update mcast bins for VFs, PF doesn't use this functionality */ 7368c2ecf20Sopenharmony_ci qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params); 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci qed_sp_update_accept_mode(p_hwfn, p_ramrod, p_params->accept_flags); 7398c2ecf20Sopenharmony_ci qed_sp_vport_update_sge_tpa(p_hwfn, p_ramrod, p_params->sge_tpa_params); 7408c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 7418c2ecf20Sopenharmony_ci} 7428c2ecf20Sopenharmony_ci 7438c2ecf20Sopenharmony_ciint qed_sp_vport_stop(struct qed_hwfn *p_hwfn, u16 opaque_fid, u8 vport_id) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct vport_stop_ramrod_data *p_ramrod; 7468c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 7478c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent; 7488c2ecf20Sopenharmony_ci u8 abs_vport_id = 0; 7498c2ecf20Sopenharmony_ci int rc; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (IS_VF(p_hwfn->cdev)) 7528c2ecf20Sopenharmony_ci return qed_vf_pf_vport_stop(p_hwfn); 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id); 7558c2ecf20Sopenharmony_ci if (rc) 7568c2ecf20Sopenharmony_ci return rc; 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 7598c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 7608c2ecf20Sopenharmony_ci init_data.opaque_fid = opaque_fid; 7618c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 7648c2ecf20Sopenharmony_ci ETH_RAMROD_VPORT_STOP, 7658c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 7668c2ecf20Sopenharmony_ci if (rc) 7678c2ecf20Sopenharmony_ci return rc; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.vport_stop; 7708c2ecf20Sopenharmony_ci p_ramrod->vport_id = abs_vport_id; 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 7738c2ecf20Sopenharmony_ci} 7748c2ecf20Sopenharmony_ci 7758c2ecf20Sopenharmony_cistatic int 7768c2ecf20Sopenharmony_ciqed_vf_pf_accept_flags(struct qed_hwfn *p_hwfn, 7778c2ecf20Sopenharmony_ci struct qed_filter_accept_flags *p_accept_flags) 7788c2ecf20Sopenharmony_ci{ 7798c2ecf20Sopenharmony_ci struct qed_sp_vport_update_params s_params; 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci memset(&s_params, 0, sizeof(s_params)); 7828c2ecf20Sopenharmony_ci memcpy(&s_params.accept_flags, p_accept_flags, 7838c2ecf20Sopenharmony_ci sizeof(struct qed_filter_accept_flags)); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci return qed_vf_pf_vport_update(p_hwfn, &s_params); 7868c2ecf20Sopenharmony_ci} 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_cistatic int qed_filter_accept_cmd(struct qed_dev *cdev, 7898c2ecf20Sopenharmony_ci u8 vport, 7908c2ecf20Sopenharmony_ci struct qed_filter_accept_flags accept_flags, 7918c2ecf20Sopenharmony_ci u8 update_accept_any_vlan, 7928c2ecf20Sopenharmony_ci u8 accept_any_vlan, 7938c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 7948c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci struct qed_sp_vport_update_params vport_update_params; 7978c2ecf20Sopenharmony_ci int i, rc; 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci /* Prepare and send the vport rx_mode change */ 8008c2ecf20Sopenharmony_ci memset(&vport_update_params, 0, sizeof(vport_update_params)); 8018c2ecf20Sopenharmony_ci vport_update_params.vport_id = vport; 8028c2ecf20Sopenharmony_ci vport_update_params.accept_flags = accept_flags; 8038c2ecf20Sopenharmony_ci vport_update_params.update_accept_any_vlan_flg = update_accept_any_vlan; 8048c2ecf20Sopenharmony_ci vport_update_params.accept_any_vlan = accept_any_vlan; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 8078c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci vport_update_params.opaque_fid = p_hwfn->hw_info.opaque_fid; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci if (IS_VF(cdev)) { 8128c2ecf20Sopenharmony_ci rc = qed_vf_pf_accept_flags(p_hwfn, &accept_flags); 8138c2ecf20Sopenharmony_ci if (rc) 8148c2ecf20Sopenharmony_ci return rc; 8158c2ecf20Sopenharmony_ci continue; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci rc = qed_sp_vport_update(p_hwfn, &vport_update_params, 8198c2ecf20Sopenharmony_ci comp_mode, p_comp_data); 8208c2ecf20Sopenharmony_ci if (rc) { 8218c2ecf20Sopenharmony_ci DP_ERR(cdev, "Update rx_mode failed %d\n", rc); 8228c2ecf20Sopenharmony_ci return rc; 8238c2ecf20Sopenharmony_ci } 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 8268c2ecf20Sopenharmony_ci "Accept filter configured, flags = [Rx]%x [Tx]%x\n", 8278c2ecf20Sopenharmony_ci accept_flags.rx_accept_filter, 8288c2ecf20Sopenharmony_ci accept_flags.tx_accept_filter); 8298c2ecf20Sopenharmony_ci if (update_accept_any_vlan) 8308c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 8318c2ecf20Sopenharmony_ci "accept_any_vlan=%d configured\n", 8328c2ecf20Sopenharmony_ci accept_any_vlan); 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci return 0; 8368c2ecf20Sopenharmony_ci} 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ciint qed_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn, 8398c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, 8408c2ecf20Sopenharmony_ci u16 bd_max_bytes, 8418c2ecf20Sopenharmony_ci dma_addr_t bd_chain_phys_addr, 8428c2ecf20Sopenharmony_ci dma_addr_t cqe_pbl_addr, u16 cqe_pbl_size) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct rx_queue_start_ramrod_data *p_ramrod = NULL; 8458c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 8468c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 8478c2ecf20Sopenharmony_ci int rc = -EINVAL; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 8508c2ecf20Sopenharmony_ci "opaque_fid=0x%x, cid=0x%x, rx_qzone=0x%x, vport_id=0x%x, sb_id=0x%x\n", 8518c2ecf20Sopenharmony_ci p_cid->opaque_fid, p_cid->cid, 8528c2ecf20Sopenharmony_ci p_cid->abs.queue_id, p_cid->abs.vport_id, p_cid->sb_igu_id); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci /* Get SPQ entry */ 8558c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 8568c2ecf20Sopenharmony_ci init_data.cid = p_cid->cid; 8578c2ecf20Sopenharmony_ci init_data.opaque_fid = p_cid->opaque_fid; 8588c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 8618c2ecf20Sopenharmony_ci ETH_RAMROD_RX_QUEUE_START, 8628c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 8638c2ecf20Sopenharmony_ci if (rc) 8648c2ecf20Sopenharmony_ci return rc; 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.rx_queue_start; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci p_ramrod->sb_id = cpu_to_le16(p_cid->sb_igu_id); 8698c2ecf20Sopenharmony_ci p_ramrod->sb_index = p_cid->sb_idx; 8708c2ecf20Sopenharmony_ci p_ramrod->vport_id = p_cid->abs.vport_id; 8718c2ecf20Sopenharmony_ci p_ramrod->stats_counter_id = p_cid->abs.stats_id; 8728c2ecf20Sopenharmony_ci p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id); 8738c2ecf20Sopenharmony_ci p_ramrod->complete_cqe_flg = 0; 8748c2ecf20Sopenharmony_ci p_ramrod->complete_event_flg = 1; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci p_ramrod->bd_max_bytes = cpu_to_le16(bd_max_bytes); 8778c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_ramrod->bd_base, bd_chain_phys_addr); 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size); 8808c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr, cqe_pbl_addr); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci if (p_cid->vfid != QED_QUEUE_CID_SELF) { 8838c2ecf20Sopenharmony_ci bool b_legacy_vf = !!(p_cid->vf_legacy & 8848c2ecf20Sopenharmony_ci QED_QCID_LEGACY_VF_RX_PROD); 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci p_ramrod->vf_rx_prod_index = p_cid->vf_qid; 8878c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 8888c2ecf20Sopenharmony_ci "Queue%s is meant for VF rxq[%02x]\n", 8898c2ecf20Sopenharmony_ci b_legacy_vf ? " [legacy]" : "", p_cid->vf_qid); 8908c2ecf20Sopenharmony_ci p_ramrod->vf_rx_prod_use_zone_a = b_legacy_vf; 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic int 8978c2ecf20Sopenharmony_ciqed_eth_pf_rx_queue_start(struct qed_hwfn *p_hwfn, 8988c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, 8998c2ecf20Sopenharmony_ci u16 bd_max_bytes, 9008c2ecf20Sopenharmony_ci dma_addr_t bd_chain_phys_addr, 9018c2ecf20Sopenharmony_ci dma_addr_t cqe_pbl_addr, 9028c2ecf20Sopenharmony_ci u16 cqe_pbl_size, void __iomem **pp_prod) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci u32 init_prod_val = 0; 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci *pp_prod = p_hwfn->regview + 9078c2ecf20Sopenharmony_ci GTT_BAR0_MAP_REG_MSDM_RAM + 9088c2ecf20Sopenharmony_ci MSTORM_ETH_PF_PRODS_OFFSET(p_cid->abs.queue_id); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */ 9118c2ecf20Sopenharmony_ci __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32), 9128c2ecf20Sopenharmony_ci (u32 *)(&init_prod_val)); 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci return qed_eth_rxq_start_ramrod(p_hwfn, p_cid, 9158c2ecf20Sopenharmony_ci bd_max_bytes, 9168c2ecf20Sopenharmony_ci bd_chain_phys_addr, 9178c2ecf20Sopenharmony_ci cqe_pbl_addr, cqe_pbl_size); 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic int 9218c2ecf20Sopenharmony_ciqed_eth_rx_queue_start(struct qed_hwfn *p_hwfn, 9228c2ecf20Sopenharmony_ci u16 opaque_fid, 9238c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 9248c2ecf20Sopenharmony_ci u16 bd_max_bytes, 9258c2ecf20Sopenharmony_ci dma_addr_t bd_chain_phys_addr, 9268c2ecf20Sopenharmony_ci dma_addr_t cqe_pbl_addr, 9278c2ecf20Sopenharmony_ci u16 cqe_pbl_size, 9288c2ecf20Sopenharmony_ci struct qed_rxq_start_ret_params *p_ret_params) 9298c2ecf20Sopenharmony_ci{ 9308c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid; 9318c2ecf20Sopenharmony_ci int rc; 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci /* Allocate a CID for the queue */ 9348c2ecf20Sopenharmony_ci p_cid = qed_eth_queue_to_cid_pf(p_hwfn, opaque_fid, true, p_params); 9358c2ecf20Sopenharmony_ci if (!p_cid) 9368c2ecf20Sopenharmony_ci return -ENOMEM; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 9398c2ecf20Sopenharmony_ci rc = qed_eth_pf_rx_queue_start(p_hwfn, p_cid, 9408c2ecf20Sopenharmony_ci bd_max_bytes, 9418c2ecf20Sopenharmony_ci bd_chain_phys_addr, 9428c2ecf20Sopenharmony_ci cqe_pbl_addr, cqe_pbl_size, 9438c2ecf20Sopenharmony_ci &p_ret_params->p_prod); 9448c2ecf20Sopenharmony_ci } else { 9458c2ecf20Sopenharmony_ci rc = qed_vf_pf_rxq_start(p_hwfn, p_cid, 9468c2ecf20Sopenharmony_ci bd_max_bytes, 9478c2ecf20Sopenharmony_ci bd_chain_phys_addr, 9488c2ecf20Sopenharmony_ci cqe_pbl_addr, 9498c2ecf20Sopenharmony_ci cqe_pbl_size, &p_ret_params->p_prod); 9508c2ecf20Sopenharmony_ci } 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* Provide the caller with a reference to as handler */ 9538c2ecf20Sopenharmony_ci if (rc) 9548c2ecf20Sopenharmony_ci qed_eth_queue_cid_release(p_hwfn, p_cid); 9558c2ecf20Sopenharmony_ci else 9568c2ecf20Sopenharmony_ci p_ret_params->p_handle = (void *)p_cid; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci return rc; 9598c2ecf20Sopenharmony_ci} 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ciint qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn, 9628c2ecf20Sopenharmony_ci void **pp_rxq_handles, 9638c2ecf20Sopenharmony_ci u8 num_rxqs, 9648c2ecf20Sopenharmony_ci u8 complete_cqe_flg, 9658c2ecf20Sopenharmony_ci u8 complete_event_flg, 9668c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 9678c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 9688c2ecf20Sopenharmony_ci{ 9698c2ecf20Sopenharmony_ci struct rx_queue_update_ramrod_data *p_ramrod = NULL; 9708c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 9718c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 9728c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid; 9738c2ecf20Sopenharmony_ci int rc = -EINVAL; 9748c2ecf20Sopenharmony_ci u8 i; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 9778c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 9788c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_data; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci for (i = 0; i < num_rxqs; i++) { 9818c2ecf20Sopenharmony_ci p_cid = ((struct qed_queue_cid **)pp_rxq_handles)[i]; 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci /* Get SPQ entry */ 9848c2ecf20Sopenharmony_ci init_data.cid = p_cid->cid; 9858c2ecf20Sopenharmony_ci init_data.opaque_fid = p_cid->opaque_fid; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 9888c2ecf20Sopenharmony_ci ETH_RAMROD_RX_QUEUE_UPDATE, 9898c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 9908c2ecf20Sopenharmony_ci if (rc) 9918c2ecf20Sopenharmony_ci return rc; 9928c2ecf20Sopenharmony_ci 9938c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.rx_queue_update; 9948c2ecf20Sopenharmony_ci p_ramrod->vport_id = p_cid->abs.vport_id; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id); 9978c2ecf20Sopenharmony_ci p_ramrod->complete_cqe_flg = complete_cqe_flg; 9988c2ecf20Sopenharmony_ci p_ramrod->complete_event_flg = complete_event_flg; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci rc = qed_spq_post(p_hwfn, p_ent, NULL); 10018c2ecf20Sopenharmony_ci if (rc) 10028c2ecf20Sopenharmony_ci return rc; 10038c2ecf20Sopenharmony_ci } 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci return rc; 10068c2ecf20Sopenharmony_ci} 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_cistatic int 10098c2ecf20Sopenharmony_ciqed_eth_pf_rx_queue_stop(struct qed_hwfn *p_hwfn, 10108c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, 10118c2ecf20Sopenharmony_ci bool b_eq_completion_only, bool b_cqe_completion) 10128c2ecf20Sopenharmony_ci{ 10138c2ecf20Sopenharmony_ci struct rx_queue_stop_ramrod_data *p_ramrod = NULL; 10148c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 10158c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 10168c2ecf20Sopenharmony_ci int rc; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 10198c2ecf20Sopenharmony_ci init_data.cid = p_cid->cid; 10208c2ecf20Sopenharmony_ci init_data.opaque_fid = p_cid->opaque_fid; 10218c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 10248c2ecf20Sopenharmony_ci ETH_RAMROD_RX_QUEUE_STOP, 10258c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 10268c2ecf20Sopenharmony_ci if (rc) 10278c2ecf20Sopenharmony_ci return rc; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.rx_queue_stop; 10308c2ecf20Sopenharmony_ci p_ramrod->vport_id = p_cid->abs.vport_id; 10318c2ecf20Sopenharmony_ci p_ramrod->rx_queue_id = cpu_to_le16(p_cid->abs.queue_id); 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_ci /* Cleaning the queue requires the completion to arrive there. 10348c2ecf20Sopenharmony_ci * In addition, VFs require the answer to come as eqe to PF. 10358c2ecf20Sopenharmony_ci */ 10368c2ecf20Sopenharmony_ci p_ramrod->complete_cqe_flg = ((p_cid->vfid == QED_QUEUE_CID_SELF) && 10378c2ecf20Sopenharmony_ci !b_eq_completion_only) || 10388c2ecf20Sopenharmony_ci b_cqe_completion; 10398c2ecf20Sopenharmony_ci p_ramrod->complete_event_flg = (p_cid->vfid != QED_QUEUE_CID_SELF) || 10408c2ecf20Sopenharmony_ci b_eq_completion_only; 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ciint qed_eth_rx_queue_stop(struct qed_hwfn *p_hwfn, 10468c2ecf20Sopenharmony_ci void *p_rxq, 10478c2ecf20Sopenharmony_ci bool eq_completion_only, bool cqe_completion) 10488c2ecf20Sopenharmony_ci{ 10498c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_rxq; 10508c2ecf20Sopenharmony_ci int rc = -EINVAL; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) 10538c2ecf20Sopenharmony_ci rc = qed_eth_pf_rx_queue_stop(p_hwfn, p_cid, 10548c2ecf20Sopenharmony_ci eq_completion_only, 10558c2ecf20Sopenharmony_ci cqe_completion); 10568c2ecf20Sopenharmony_ci else 10578c2ecf20Sopenharmony_ci rc = qed_vf_pf_rxq_stop(p_hwfn, p_cid, cqe_completion); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci if (!rc) 10608c2ecf20Sopenharmony_ci qed_eth_queue_cid_release(p_hwfn, p_cid); 10618c2ecf20Sopenharmony_ci return rc; 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_ciint 10658c2ecf20Sopenharmony_ciqed_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn, 10668c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, 10678c2ecf20Sopenharmony_ci dma_addr_t pbl_addr, u16 pbl_size, u16 pq_id) 10688c2ecf20Sopenharmony_ci{ 10698c2ecf20Sopenharmony_ci struct tx_queue_start_ramrod_data *p_ramrod = NULL; 10708c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 10718c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 10728c2ecf20Sopenharmony_ci int rc = -EINVAL; 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci /* Get SPQ entry */ 10758c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 10768c2ecf20Sopenharmony_ci init_data.cid = p_cid->cid; 10778c2ecf20Sopenharmony_ci init_data.opaque_fid = p_cid->opaque_fid; 10788c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 10818c2ecf20Sopenharmony_ci ETH_RAMROD_TX_QUEUE_START, 10828c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 10838c2ecf20Sopenharmony_ci if (rc) 10848c2ecf20Sopenharmony_ci return rc; 10858c2ecf20Sopenharmony_ci 10868c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.tx_queue_start; 10878c2ecf20Sopenharmony_ci p_ramrod->vport_id = p_cid->abs.vport_id; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci p_ramrod->sb_id = cpu_to_le16(p_cid->sb_igu_id); 10908c2ecf20Sopenharmony_ci p_ramrod->sb_index = p_cid->sb_idx; 10918c2ecf20Sopenharmony_ci p_ramrod->stats_counter_id = p_cid->abs.stats_id; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci p_ramrod->queue_zone_id = cpu_to_le16(p_cid->abs.queue_id); 10948c2ecf20Sopenharmony_ci p_ramrod->same_as_last_id = cpu_to_le16(p_cid->abs.queue_id); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci p_ramrod->pbl_size = cpu_to_le16(pbl_size); 10978c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_ramrod->pbl_base_addr, pbl_addr); 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci p_ramrod->qm_pq_id = cpu_to_le16(pq_id); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 11028c2ecf20Sopenharmony_ci} 11038c2ecf20Sopenharmony_ci 11048c2ecf20Sopenharmony_cistatic int 11058c2ecf20Sopenharmony_ciqed_eth_pf_tx_queue_start(struct qed_hwfn *p_hwfn, 11068c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, 11078c2ecf20Sopenharmony_ci u8 tc, 11088c2ecf20Sopenharmony_ci dma_addr_t pbl_addr, 11098c2ecf20Sopenharmony_ci u16 pbl_size, void __iomem **pp_doorbell) 11108c2ecf20Sopenharmony_ci{ 11118c2ecf20Sopenharmony_ci int rc; 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci rc = qed_eth_txq_start_ramrod(p_hwfn, p_cid, 11158c2ecf20Sopenharmony_ci pbl_addr, pbl_size, 11168c2ecf20Sopenharmony_ci qed_get_cm_pq_idx_mcos(p_hwfn, tc)); 11178c2ecf20Sopenharmony_ci if (rc) 11188c2ecf20Sopenharmony_ci return rc; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* Provide the caller with the necessary return values */ 11218c2ecf20Sopenharmony_ci *pp_doorbell = p_hwfn->doorbells + 11228c2ecf20Sopenharmony_ci qed_db_addr(p_cid->cid, DQ_DEMS_LEGACY); 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci return 0; 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_cistatic int 11288c2ecf20Sopenharmony_ciqed_eth_tx_queue_start(struct qed_hwfn *p_hwfn, 11298c2ecf20Sopenharmony_ci u16 opaque_fid, 11308c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 11318c2ecf20Sopenharmony_ci u8 tc, 11328c2ecf20Sopenharmony_ci dma_addr_t pbl_addr, 11338c2ecf20Sopenharmony_ci u16 pbl_size, 11348c2ecf20Sopenharmony_ci struct qed_txq_start_ret_params *p_ret_params) 11358c2ecf20Sopenharmony_ci{ 11368c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid; 11378c2ecf20Sopenharmony_ci int rc; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci p_cid = qed_eth_queue_to_cid_pf(p_hwfn, opaque_fid, false, p_params); 11408c2ecf20Sopenharmony_ci if (!p_cid) 11418c2ecf20Sopenharmony_ci return -EINVAL; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) 11448c2ecf20Sopenharmony_ci rc = qed_eth_pf_tx_queue_start(p_hwfn, p_cid, tc, 11458c2ecf20Sopenharmony_ci pbl_addr, pbl_size, 11468c2ecf20Sopenharmony_ci &p_ret_params->p_doorbell); 11478c2ecf20Sopenharmony_ci else 11488c2ecf20Sopenharmony_ci rc = qed_vf_pf_txq_start(p_hwfn, p_cid, 11498c2ecf20Sopenharmony_ci pbl_addr, pbl_size, 11508c2ecf20Sopenharmony_ci &p_ret_params->p_doorbell); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci if (rc) 11538c2ecf20Sopenharmony_ci qed_eth_queue_cid_release(p_hwfn, p_cid); 11548c2ecf20Sopenharmony_ci else 11558c2ecf20Sopenharmony_ci p_ret_params->p_handle = (void *)p_cid; 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci return rc; 11588c2ecf20Sopenharmony_ci} 11598c2ecf20Sopenharmony_ci 11608c2ecf20Sopenharmony_cistatic int 11618c2ecf20Sopenharmony_ciqed_eth_pf_tx_queue_stop(struct qed_hwfn *p_hwfn, struct qed_queue_cid *p_cid) 11628c2ecf20Sopenharmony_ci{ 11638c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 11648c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 11658c2ecf20Sopenharmony_ci int rc; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 11688c2ecf20Sopenharmony_ci init_data.cid = p_cid->cid; 11698c2ecf20Sopenharmony_ci init_data.opaque_fid = p_cid->opaque_fid; 11708c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 11738c2ecf20Sopenharmony_ci ETH_RAMROD_TX_QUEUE_STOP, 11748c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 11758c2ecf20Sopenharmony_ci if (rc) 11768c2ecf20Sopenharmony_ci return rc; 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ciint qed_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, void *p_handle) 11828c2ecf20Sopenharmony_ci{ 11838c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid = (struct qed_queue_cid *)p_handle; 11848c2ecf20Sopenharmony_ci int rc; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) 11878c2ecf20Sopenharmony_ci rc = qed_eth_pf_tx_queue_stop(p_hwfn, p_cid); 11888c2ecf20Sopenharmony_ci else 11898c2ecf20Sopenharmony_ci rc = qed_vf_pf_txq_stop(p_hwfn, p_cid); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci if (!rc) 11928c2ecf20Sopenharmony_ci qed_eth_queue_cid_release(p_hwfn, p_cid); 11938c2ecf20Sopenharmony_ci return rc; 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_cistatic enum eth_filter_action qed_filter_action(enum qed_filter_opcode opcode) 11978c2ecf20Sopenharmony_ci{ 11988c2ecf20Sopenharmony_ci enum eth_filter_action action = MAX_ETH_FILTER_ACTION; 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci switch (opcode) { 12018c2ecf20Sopenharmony_ci case QED_FILTER_ADD: 12028c2ecf20Sopenharmony_ci action = ETH_FILTER_ACTION_ADD; 12038c2ecf20Sopenharmony_ci break; 12048c2ecf20Sopenharmony_ci case QED_FILTER_REMOVE: 12058c2ecf20Sopenharmony_ci action = ETH_FILTER_ACTION_REMOVE; 12068c2ecf20Sopenharmony_ci break; 12078c2ecf20Sopenharmony_ci case QED_FILTER_FLUSH: 12088c2ecf20Sopenharmony_ci action = ETH_FILTER_ACTION_REMOVE_ALL; 12098c2ecf20Sopenharmony_ci break; 12108c2ecf20Sopenharmony_ci default: 12118c2ecf20Sopenharmony_ci action = MAX_ETH_FILTER_ACTION; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci return action; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic int 12188c2ecf20Sopenharmony_ciqed_filter_ucast_common(struct qed_hwfn *p_hwfn, 12198c2ecf20Sopenharmony_ci u16 opaque_fid, 12208c2ecf20Sopenharmony_ci struct qed_filter_ucast *p_filter_cmd, 12218c2ecf20Sopenharmony_ci struct vport_filter_update_ramrod_data **pp_ramrod, 12228c2ecf20Sopenharmony_ci struct qed_spq_entry **pp_ent, 12238c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 12248c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 12258c2ecf20Sopenharmony_ci{ 12268c2ecf20Sopenharmony_ci u8 vport_to_add_to = 0, vport_to_remove_from = 0; 12278c2ecf20Sopenharmony_ci struct vport_filter_update_ramrod_data *p_ramrod; 12288c2ecf20Sopenharmony_ci struct eth_filter_cmd *p_first_filter; 12298c2ecf20Sopenharmony_ci struct eth_filter_cmd *p_second_filter; 12308c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 12318c2ecf20Sopenharmony_ci enum eth_filter_action action; 12328c2ecf20Sopenharmony_ci int rc; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from, 12358c2ecf20Sopenharmony_ci &vport_to_remove_from); 12368c2ecf20Sopenharmony_ci if (rc) 12378c2ecf20Sopenharmony_ci return rc; 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to, 12408c2ecf20Sopenharmony_ci &vport_to_add_to); 12418c2ecf20Sopenharmony_ci if (rc) 12428c2ecf20Sopenharmony_ci return rc; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci /* Get SPQ entry */ 12458c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 12468c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 12478c2ecf20Sopenharmony_ci init_data.opaque_fid = opaque_fid; 12488c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 12498c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_data; 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, pp_ent, 12528c2ecf20Sopenharmony_ci ETH_RAMROD_FILTERS_UPDATE, 12538c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 12548c2ecf20Sopenharmony_ci if (rc) 12558c2ecf20Sopenharmony_ci return rc; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci *pp_ramrod = &(*pp_ent)->ramrod.vport_filter_update; 12588c2ecf20Sopenharmony_ci p_ramrod = *pp_ramrod; 12598c2ecf20Sopenharmony_ci p_ramrod->filter_cmd_hdr.rx = p_filter_cmd->is_rx_filter ? 1 : 0; 12608c2ecf20Sopenharmony_ci p_ramrod->filter_cmd_hdr.tx = p_filter_cmd->is_tx_filter ? 1 : 0; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci switch (p_filter_cmd->opcode) { 12638c2ecf20Sopenharmony_ci case QED_FILTER_REPLACE: 12648c2ecf20Sopenharmony_ci case QED_FILTER_MOVE: 12658c2ecf20Sopenharmony_ci p_ramrod->filter_cmd_hdr.cmd_cnt = 2; break; 12668c2ecf20Sopenharmony_ci default: 12678c2ecf20Sopenharmony_ci p_ramrod->filter_cmd_hdr.cmd_cnt = 1; break; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci p_first_filter = &p_ramrod->filter_cmds[0]; 12718c2ecf20Sopenharmony_ci p_second_filter = &p_ramrod->filter_cmds[1]; 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci switch (p_filter_cmd->type) { 12748c2ecf20Sopenharmony_ci case QED_FILTER_MAC: 12758c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_MAC; break; 12768c2ecf20Sopenharmony_ci case QED_FILTER_VLAN: 12778c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_VLAN; break; 12788c2ecf20Sopenharmony_ci case QED_FILTER_MAC_VLAN: 12798c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_PAIR; break; 12808c2ecf20Sopenharmony_ci case QED_FILTER_INNER_MAC: 12818c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC; break; 12828c2ecf20Sopenharmony_ci case QED_FILTER_INNER_VLAN: 12838c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_INNER_VLAN; break; 12848c2ecf20Sopenharmony_ci case QED_FILTER_INNER_PAIR: 12858c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_INNER_PAIR; break; 12868c2ecf20Sopenharmony_ci case QED_FILTER_INNER_MAC_VNI_PAIR: 12878c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR; 12888c2ecf20Sopenharmony_ci break; 12898c2ecf20Sopenharmony_ci case QED_FILTER_MAC_VNI_PAIR: 12908c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_MAC_VNI_PAIR; break; 12918c2ecf20Sopenharmony_ci case QED_FILTER_VNI: 12928c2ecf20Sopenharmony_ci p_first_filter->type = ETH_FILTER_TYPE_VNI; break; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci if ((p_first_filter->type == ETH_FILTER_TYPE_MAC) || 12968c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_PAIR) || 12978c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC) || 12988c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR) || 12998c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) || 13008c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR)) { 13018c2ecf20Sopenharmony_ci qed_set_fw_mac_addr(&p_first_filter->mac_msb, 13028c2ecf20Sopenharmony_ci &p_first_filter->mac_mid, 13038c2ecf20Sopenharmony_ci &p_first_filter->mac_lsb, 13048c2ecf20Sopenharmony_ci (u8 *)p_filter_cmd->mac); 13058c2ecf20Sopenharmony_ci } 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci if ((p_first_filter->type == ETH_FILTER_TYPE_VLAN) || 13088c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_PAIR) || 13098c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_INNER_VLAN) || 13108c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_INNER_PAIR)) 13118c2ecf20Sopenharmony_ci p_first_filter->vlan_id = cpu_to_le16(p_filter_cmd->vlan); 13128c2ecf20Sopenharmony_ci 13138c2ecf20Sopenharmony_ci if ((p_first_filter->type == ETH_FILTER_TYPE_INNER_MAC_VNI_PAIR) || 13148c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_MAC_VNI_PAIR) || 13158c2ecf20Sopenharmony_ci (p_first_filter->type == ETH_FILTER_TYPE_VNI)) 13168c2ecf20Sopenharmony_ci p_first_filter->vni = cpu_to_le32(p_filter_cmd->vni); 13178c2ecf20Sopenharmony_ci 13188c2ecf20Sopenharmony_ci if (p_filter_cmd->opcode == QED_FILTER_MOVE) { 13198c2ecf20Sopenharmony_ci p_second_filter->type = p_first_filter->type; 13208c2ecf20Sopenharmony_ci p_second_filter->mac_msb = p_first_filter->mac_msb; 13218c2ecf20Sopenharmony_ci p_second_filter->mac_mid = p_first_filter->mac_mid; 13228c2ecf20Sopenharmony_ci p_second_filter->mac_lsb = p_first_filter->mac_lsb; 13238c2ecf20Sopenharmony_ci p_second_filter->vlan_id = p_first_filter->vlan_id; 13248c2ecf20Sopenharmony_ci p_second_filter->vni = p_first_filter->vni; 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci p_first_filter->action = ETH_FILTER_ACTION_REMOVE; 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_ci p_first_filter->vport_id = vport_to_remove_from; 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci p_second_filter->action = ETH_FILTER_ACTION_ADD; 13318c2ecf20Sopenharmony_ci p_second_filter->vport_id = vport_to_add_to; 13328c2ecf20Sopenharmony_ci } else if (p_filter_cmd->opcode == QED_FILTER_REPLACE) { 13338c2ecf20Sopenharmony_ci p_first_filter->vport_id = vport_to_add_to; 13348c2ecf20Sopenharmony_ci memcpy(p_second_filter, p_first_filter, 13358c2ecf20Sopenharmony_ci sizeof(*p_second_filter)); 13368c2ecf20Sopenharmony_ci p_first_filter->action = ETH_FILTER_ACTION_REMOVE_ALL; 13378c2ecf20Sopenharmony_ci p_second_filter->action = ETH_FILTER_ACTION_ADD; 13388c2ecf20Sopenharmony_ci } else { 13398c2ecf20Sopenharmony_ci action = qed_filter_action(p_filter_cmd->opcode); 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci if (action == MAX_ETH_FILTER_ACTION) { 13428c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 13438c2ecf20Sopenharmony_ci "%d is not supported yet\n", 13448c2ecf20Sopenharmony_ci p_filter_cmd->opcode); 13458c2ecf20Sopenharmony_ci qed_sp_destroy_request(p_hwfn, *pp_ent); 13468c2ecf20Sopenharmony_ci return -EINVAL; 13478c2ecf20Sopenharmony_ci } 13488c2ecf20Sopenharmony_ci 13498c2ecf20Sopenharmony_ci p_first_filter->action = action; 13508c2ecf20Sopenharmony_ci p_first_filter->vport_id = (p_filter_cmd->opcode == 13518c2ecf20Sopenharmony_ci QED_FILTER_REMOVE) ? 13528c2ecf20Sopenharmony_ci vport_to_remove_from : 13538c2ecf20Sopenharmony_ci vport_to_add_to; 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci return 0; 13578c2ecf20Sopenharmony_ci} 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ciint qed_sp_eth_filter_ucast(struct qed_hwfn *p_hwfn, 13608c2ecf20Sopenharmony_ci u16 opaque_fid, 13618c2ecf20Sopenharmony_ci struct qed_filter_ucast *p_filter_cmd, 13628c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 13638c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 13648c2ecf20Sopenharmony_ci{ 13658c2ecf20Sopenharmony_ci struct vport_filter_update_ramrod_data *p_ramrod = NULL; 13668c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 13678c2ecf20Sopenharmony_ci struct eth_filter_cmd_header *p_header; 13688c2ecf20Sopenharmony_ci int rc; 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci rc = qed_filter_ucast_common(p_hwfn, opaque_fid, p_filter_cmd, 13718c2ecf20Sopenharmony_ci &p_ramrod, &p_ent, 13728c2ecf20Sopenharmony_ci comp_mode, p_comp_data); 13738c2ecf20Sopenharmony_ci if (rc) { 13748c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Uni. filter command failed %d\n", rc); 13758c2ecf20Sopenharmony_ci return rc; 13768c2ecf20Sopenharmony_ci } 13778c2ecf20Sopenharmony_ci p_header = &p_ramrod->filter_cmd_hdr; 13788c2ecf20Sopenharmony_ci p_header->assert_on_error = p_filter_cmd->assert_on_error; 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci rc = qed_spq_post(p_hwfn, p_ent, NULL); 13818c2ecf20Sopenharmony_ci if (rc) { 13828c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Unicast filter ADD command failed %d\n", rc); 13838c2ecf20Sopenharmony_ci return rc; 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 13878c2ecf20Sopenharmony_ci "Unicast filter configured, opcode = %s, type = %s, cmd_cnt = %d, is_rx_filter = %d, is_tx_filter = %d\n", 13888c2ecf20Sopenharmony_ci (p_filter_cmd->opcode == QED_FILTER_ADD) ? "ADD" : 13898c2ecf20Sopenharmony_ci ((p_filter_cmd->opcode == QED_FILTER_REMOVE) ? 13908c2ecf20Sopenharmony_ci "REMOVE" : 13918c2ecf20Sopenharmony_ci ((p_filter_cmd->opcode == QED_FILTER_MOVE) ? 13928c2ecf20Sopenharmony_ci "MOVE" : "REPLACE")), 13938c2ecf20Sopenharmony_ci (p_filter_cmd->type == QED_FILTER_MAC) ? "MAC" : 13948c2ecf20Sopenharmony_ci ((p_filter_cmd->type == QED_FILTER_VLAN) ? 13958c2ecf20Sopenharmony_ci "VLAN" : "MAC & VLAN"), 13968c2ecf20Sopenharmony_ci p_ramrod->filter_cmd_hdr.cmd_cnt, 13978c2ecf20Sopenharmony_ci p_filter_cmd->is_rx_filter, 13988c2ecf20Sopenharmony_ci p_filter_cmd->is_tx_filter); 13998c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 14008c2ecf20Sopenharmony_ci "vport_to_add_to = %d, vport_to_remove_from = %d, mac = %2x:%2x:%2x:%2x:%2x:%2x, vlan = %d\n", 14018c2ecf20Sopenharmony_ci p_filter_cmd->vport_to_add_to, 14028c2ecf20Sopenharmony_ci p_filter_cmd->vport_to_remove_from, 14038c2ecf20Sopenharmony_ci p_filter_cmd->mac[0], 14048c2ecf20Sopenharmony_ci p_filter_cmd->mac[1], 14058c2ecf20Sopenharmony_ci p_filter_cmd->mac[2], 14068c2ecf20Sopenharmony_ci p_filter_cmd->mac[3], 14078c2ecf20Sopenharmony_ci p_filter_cmd->mac[4], 14088c2ecf20Sopenharmony_ci p_filter_cmd->mac[5], 14098c2ecf20Sopenharmony_ci p_filter_cmd->vlan); 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci return 0; 14128c2ecf20Sopenharmony_ci} 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci/******************************************************************************* 14158c2ecf20Sopenharmony_ci * Description: 14168c2ecf20Sopenharmony_ci * Calculates crc 32 on a buffer 14178c2ecf20Sopenharmony_ci * Note: crc32_length MUST be aligned to 8 14188c2ecf20Sopenharmony_ci * Return: 14198c2ecf20Sopenharmony_ci ******************************************************************************/ 14208c2ecf20Sopenharmony_cistatic u32 qed_calc_crc32c(u8 *crc32_packet, 14218c2ecf20Sopenharmony_ci u32 crc32_length, u32 crc32_seed, u8 complement) 14228c2ecf20Sopenharmony_ci{ 14238c2ecf20Sopenharmony_ci u32 byte = 0, bit = 0, crc32_result = crc32_seed; 14248c2ecf20Sopenharmony_ci u8 msb = 0, current_byte = 0; 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci if ((!crc32_packet) || 14278c2ecf20Sopenharmony_ci (crc32_length == 0) || 14288c2ecf20Sopenharmony_ci ((crc32_length % 8) != 0)) 14298c2ecf20Sopenharmony_ci return crc32_result; 14308c2ecf20Sopenharmony_ci for (byte = 0; byte < crc32_length; byte++) { 14318c2ecf20Sopenharmony_ci current_byte = crc32_packet[byte]; 14328c2ecf20Sopenharmony_ci for (bit = 0; bit < 8; bit++) { 14338c2ecf20Sopenharmony_ci msb = (u8)(crc32_result >> 31); 14348c2ecf20Sopenharmony_ci crc32_result = crc32_result << 1; 14358c2ecf20Sopenharmony_ci if (msb != (0x1 & (current_byte >> bit))) { 14368c2ecf20Sopenharmony_ci crc32_result = crc32_result ^ CRC32_POLY; 14378c2ecf20Sopenharmony_ci crc32_result |= 1; /*crc32_result[0] = 1;*/ 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci } 14408c2ecf20Sopenharmony_ci } 14418c2ecf20Sopenharmony_ci return crc32_result; 14428c2ecf20Sopenharmony_ci} 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_cistatic u32 qed_crc32c_le(u32 seed, u8 *mac, u32 len) 14458c2ecf20Sopenharmony_ci{ 14468c2ecf20Sopenharmony_ci u32 packet_buf[2] = { 0 }; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci memcpy((u8 *)(&packet_buf[0]), &mac[0], 6); 14498c2ecf20Sopenharmony_ci return qed_calc_crc32c((u8 *)packet_buf, 8, seed, 0); 14508c2ecf20Sopenharmony_ci} 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ciu8 qed_mcast_bin_from_mac(u8 *mac) 14538c2ecf20Sopenharmony_ci{ 14548c2ecf20Sopenharmony_ci u32 crc = qed_crc32c_le(ETH_MULTICAST_BIN_FROM_MAC_SEED, 14558c2ecf20Sopenharmony_ci mac, ETH_ALEN); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci return crc & 0xff; 14588c2ecf20Sopenharmony_ci} 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_cistatic int 14618c2ecf20Sopenharmony_ciqed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, 14628c2ecf20Sopenharmony_ci u16 opaque_fid, 14638c2ecf20Sopenharmony_ci struct qed_filter_mcast *p_filter_cmd, 14648c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 14658c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 14668c2ecf20Sopenharmony_ci{ 14678c2ecf20Sopenharmony_ci struct vport_update_ramrod_data *p_ramrod = NULL; 14688c2ecf20Sopenharmony_ci u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; 14698c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 14708c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 14718c2ecf20Sopenharmony_ci u8 abs_vport_id = 0; 14728c2ecf20Sopenharmony_ci int rc, i; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci if (p_filter_cmd->opcode == QED_FILTER_ADD) 14758c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to, 14768c2ecf20Sopenharmony_ci &abs_vport_id); 14778c2ecf20Sopenharmony_ci else 14788c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_filter_cmd->vport_to_remove_from, 14798c2ecf20Sopenharmony_ci &abs_vport_id); 14808c2ecf20Sopenharmony_ci if (rc) 14818c2ecf20Sopenharmony_ci return rc; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci /* Get SPQ entry */ 14848c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 14858c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 14868c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 14878c2ecf20Sopenharmony_ci init_data.comp_mode = comp_mode; 14888c2ecf20Sopenharmony_ci init_data.p_comp_data = p_comp_data; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 14918c2ecf20Sopenharmony_ci ETH_RAMROD_VPORT_UPDATE, 14928c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 14938c2ecf20Sopenharmony_ci if (rc) { 14948c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Multi-cast command failed %d\n", rc); 14958c2ecf20Sopenharmony_ci return rc; 14968c2ecf20Sopenharmony_ci } 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.vport_update; 14998c2ecf20Sopenharmony_ci p_ramrod->common.update_approx_mcast_flg = 1; 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci /* explicitly clear out the entire vector */ 15028c2ecf20Sopenharmony_ci memset(&p_ramrod->approx_mcast.bins, 0, 15038c2ecf20Sopenharmony_ci sizeof(p_ramrod->approx_mcast.bins)); 15048c2ecf20Sopenharmony_ci memset(bins, 0, sizeof(bins)); 15058c2ecf20Sopenharmony_ci /* filter ADD op is explicit set op and it removes 15068c2ecf20Sopenharmony_ci * any existing filters for the vport 15078c2ecf20Sopenharmony_ci */ 15088c2ecf20Sopenharmony_ci if (p_filter_cmd->opcode == QED_FILTER_ADD) { 15098c2ecf20Sopenharmony_ci for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { 15108c2ecf20Sopenharmony_ci u32 bit, nbits; 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci bit = qed_mcast_bin_from_mac(p_filter_cmd->mac[i]); 15138c2ecf20Sopenharmony_ci nbits = sizeof(u32) * BITS_PER_BYTE; 15148c2ecf20Sopenharmony_ci bins[bit / nbits] |= 1 << (bit % nbits); 15158c2ecf20Sopenharmony_ci } 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci /* Convert to correct endianity */ 15188c2ecf20Sopenharmony_ci for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { 15198c2ecf20Sopenharmony_ci struct vport_update_ramrod_mcast *p_ramrod_bins; 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci p_ramrod_bins = &p_ramrod->approx_mcast; 15228c2ecf20Sopenharmony_ci p_ramrod_bins->bins[i] = cpu_to_le32(bins[i]); 15238c2ecf20Sopenharmony_ci } 15248c2ecf20Sopenharmony_ci } 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci p_ramrod->common.vport_id = abs_vport_id; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic int qed_filter_mcast_cmd(struct qed_dev *cdev, 15328c2ecf20Sopenharmony_ci struct qed_filter_mcast *p_filter_cmd, 15338c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 15348c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 15358c2ecf20Sopenharmony_ci{ 15368c2ecf20Sopenharmony_ci int rc = 0; 15378c2ecf20Sopenharmony_ci int i; 15388c2ecf20Sopenharmony_ci 15398c2ecf20Sopenharmony_ci /* only ADD and REMOVE operations are supported for multi-cast */ 15408c2ecf20Sopenharmony_ci if ((p_filter_cmd->opcode != QED_FILTER_ADD && 15418c2ecf20Sopenharmony_ci (p_filter_cmd->opcode != QED_FILTER_REMOVE)) || 15428c2ecf20Sopenharmony_ci (p_filter_cmd->num_mc_addrs > QED_MAX_MC_ADDRS)) 15438c2ecf20Sopenharmony_ci return -EINVAL; 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 15468c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci u16 opaque_fid; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci if (IS_VF(cdev)) { 15518c2ecf20Sopenharmony_ci qed_vf_pf_filter_mcast(p_hwfn, p_filter_cmd); 15528c2ecf20Sopenharmony_ci continue; 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci opaque_fid = p_hwfn->hw_info.opaque_fid; 15568c2ecf20Sopenharmony_ci 15578c2ecf20Sopenharmony_ci rc = qed_sp_eth_filter_mcast(p_hwfn, 15588c2ecf20Sopenharmony_ci opaque_fid, 15598c2ecf20Sopenharmony_ci p_filter_cmd, 15608c2ecf20Sopenharmony_ci comp_mode, p_comp_data); 15618c2ecf20Sopenharmony_ci } 15628c2ecf20Sopenharmony_ci return rc; 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_cistatic int qed_filter_ucast_cmd(struct qed_dev *cdev, 15668c2ecf20Sopenharmony_ci struct qed_filter_ucast *p_filter_cmd, 15678c2ecf20Sopenharmony_ci enum spq_mode comp_mode, 15688c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_comp_data) 15698c2ecf20Sopenharmony_ci{ 15708c2ecf20Sopenharmony_ci int rc = 0; 15718c2ecf20Sopenharmony_ci int i; 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 15748c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 15758c2ecf20Sopenharmony_ci u16 opaque_fid; 15768c2ecf20Sopenharmony_ci 15778c2ecf20Sopenharmony_ci if (IS_VF(cdev)) { 15788c2ecf20Sopenharmony_ci rc = qed_vf_pf_filter_ucast(p_hwfn, p_filter_cmd); 15798c2ecf20Sopenharmony_ci continue; 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci 15828c2ecf20Sopenharmony_ci opaque_fid = p_hwfn->hw_info.opaque_fid; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci rc = qed_sp_eth_filter_ucast(p_hwfn, 15858c2ecf20Sopenharmony_ci opaque_fid, 15868c2ecf20Sopenharmony_ci p_filter_cmd, 15878c2ecf20Sopenharmony_ci comp_mode, p_comp_data); 15888c2ecf20Sopenharmony_ci if (rc) 15898c2ecf20Sopenharmony_ci break; 15908c2ecf20Sopenharmony_ci } 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci return rc; 15938c2ecf20Sopenharmony_ci} 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci/* Statistics related code */ 15968c2ecf20Sopenharmony_cistatic void __qed_get_vport_pstats_addrlen(struct qed_hwfn *p_hwfn, 15978c2ecf20Sopenharmony_ci u32 *p_addr, 15988c2ecf20Sopenharmony_ci u32 *p_len, u16 statistics_bin) 15998c2ecf20Sopenharmony_ci{ 16008c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 16018c2ecf20Sopenharmony_ci *p_addr = BAR0_MAP_REG_PSDM_RAM + 16028c2ecf20Sopenharmony_ci PSTORM_QUEUE_STAT_OFFSET(statistics_bin); 16038c2ecf20Sopenharmony_ci *p_len = sizeof(struct eth_pstorm_per_queue_stat); 16048c2ecf20Sopenharmony_ci } else { 16058c2ecf20Sopenharmony_ci struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 16068c2ecf20Sopenharmony_ci struct pfvf_acquire_resp_tlv *p_resp = &p_iov->acquire_resp; 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci *p_addr = p_resp->pfdev_info.stats_info.pstats.address; 16098c2ecf20Sopenharmony_ci *p_len = p_resp->pfdev_info.stats_info.pstats.len; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci} 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_cistatic noinline_for_stack void 16148c2ecf20Sopenharmony_ci__qed_get_vport_pstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 16158c2ecf20Sopenharmony_ci struct qed_eth_stats *p_stats, u16 statistics_bin) 16168c2ecf20Sopenharmony_ci{ 16178c2ecf20Sopenharmony_ci struct eth_pstorm_per_queue_stat pstats; 16188c2ecf20Sopenharmony_ci u32 pstats_addr = 0, pstats_len = 0; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci __qed_get_vport_pstats_addrlen(p_hwfn, &pstats_addr, &pstats_len, 16218c2ecf20Sopenharmony_ci statistics_bin); 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci memset(&pstats, 0, sizeof(pstats)); 16248c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, pstats_len); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci p_stats->common.tx_ucast_bytes += 16278c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_ucast_bytes); 16288c2ecf20Sopenharmony_ci p_stats->common.tx_mcast_bytes += 16298c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_mcast_bytes); 16308c2ecf20Sopenharmony_ci p_stats->common.tx_bcast_bytes += 16318c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_bcast_bytes); 16328c2ecf20Sopenharmony_ci p_stats->common.tx_ucast_pkts += 16338c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_ucast_pkts); 16348c2ecf20Sopenharmony_ci p_stats->common.tx_mcast_pkts += 16358c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_mcast_pkts); 16368c2ecf20Sopenharmony_ci p_stats->common.tx_bcast_pkts += 16378c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.sent_bcast_pkts); 16388c2ecf20Sopenharmony_ci p_stats->common.tx_err_drop_pkts += 16398c2ecf20Sopenharmony_ci HILO_64_REGPAIR(pstats.error_drop_pkts); 16408c2ecf20Sopenharmony_ci} 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_cistatic noinline_for_stack void 16438c2ecf20Sopenharmony_ci__qed_get_vport_tstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 16448c2ecf20Sopenharmony_ci struct qed_eth_stats *p_stats, u16 statistics_bin) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci struct tstorm_per_port_stat tstats; 16478c2ecf20Sopenharmony_ci u32 tstats_addr, tstats_len; 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 16508c2ecf20Sopenharmony_ci tstats_addr = BAR0_MAP_REG_TSDM_RAM + 16518c2ecf20Sopenharmony_ci TSTORM_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)); 16528c2ecf20Sopenharmony_ci tstats_len = sizeof(struct tstorm_per_port_stat); 16538c2ecf20Sopenharmony_ci } else { 16548c2ecf20Sopenharmony_ci struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 16558c2ecf20Sopenharmony_ci struct pfvf_acquire_resp_tlv *p_resp = &p_iov->acquire_resp; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci tstats_addr = p_resp->pfdev_info.stats_info.tstats.address; 16588c2ecf20Sopenharmony_ci tstats_len = p_resp->pfdev_info.stats_info.tstats.len; 16598c2ecf20Sopenharmony_ci } 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_ci memset(&tstats, 0, sizeof(tstats)); 16628c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, tstats_len); 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci p_stats->common.mftag_filter_discards += 16658c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.mftag_filter_discard); 16668c2ecf20Sopenharmony_ci p_stats->common.mac_filter_discards += 16678c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.eth_mac_filter_discard); 16688c2ecf20Sopenharmony_ci p_stats->common.gft_filter_drop += 16698c2ecf20Sopenharmony_ci HILO_64_REGPAIR(tstats.eth_gft_drop_pkt); 16708c2ecf20Sopenharmony_ci} 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_cistatic void __qed_get_vport_ustats_addrlen(struct qed_hwfn *p_hwfn, 16738c2ecf20Sopenharmony_ci u32 *p_addr, 16748c2ecf20Sopenharmony_ci u32 *p_len, u16 statistics_bin) 16758c2ecf20Sopenharmony_ci{ 16768c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 16778c2ecf20Sopenharmony_ci *p_addr = BAR0_MAP_REG_USDM_RAM + 16788c2ecf20Sopenharmony_ci USTORM_QUEUE_STAT_OFFSET(statistics_bin); 16798c2ecf20Sopenharmony_ci *p_len = sizeof(struct eth_ustorm_per_queue_stat); 16808c2ecf20Sopenharmony_ci } else { 16818c2ecf20Sopenharmony_ci struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 16828c2ecf20Sopenharmony_ci struct pfvf_acquire_resp_tlv *p_resp = &p_iov->acquire_resp; 16838c2ecf20Sopenharmony_ci 16848c2ecf20Sopenharmony_ci *p_addr = p_resp->pfdev_info.stats_info.ustats.address; 16858c2ecf20Sopenharmony_ci *p_len = p_resp->pfdev_info.stats_info.ustats.len; 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci} 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_cistatic noinline_for_stack 16908c2ecf20Sopenharmony_civoid __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 16918c2ecf20Sopenharmony_ci struct qed_eth_stats *p_stats, u16 statistics_bin) 16928c2ecf20Sopenharmony_ci{ 16938c2ecf20Sopenharmony_ci struct eth_ustorm_per_queue_stat ustats; 16948c2ecf20Sopenharmony_ci u32 ustats_addr = 0, ustats_len = 0; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci __qed_get_vport_ustats_addrlen(p_hwfn, &ustats_addr, &ustats_len, 16978c2ecf20Sopenharmony_ci statistics_bin); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci memset(&ustats, 0, sizeof(ustats)); 17008c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &ustats, ustats_addr, ustats_len); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci p_stats->common.rx_ucast_bytes += 17038c2ecf20Sopenharmony_ci HILO_64_REGPAIR(ustats.rcv_ucast_bytes); 17048c2ecf20Sopenharmony_ci p_stats->common.rx_mcast_bytes += 17058c2ecf20Sopenharmony_ci HILO_64_REGPAIR(ustats.rcv_mcast_bytes); 17068c2ecf20Sopenharmony_ci p_stats->common.rx_bcast_bytes += 17078c2ecf20Sopenharmony_ci HILO_64_REGPAIR(ustats.rcv_bcast_bytes); 17088c2ecf20Sopenharmony_ci p_stats->common.rx_ucast_pkts += HILO_64_REGPAIR(ustats.rcv_ucast_pkts); 17098c2ecf20Sopenharmony_ci p_stats->common.rx_mcast_pkts += HILO_64_REGPAIR(ustats.rcv_mcast_pkts); 17108c2ecf20Sopenharmony_ci p_stats->common.rx_bcast_pkts += HILO_64_REGPAIR(ustats.rcv_bcast_pkts); 17118c2ecf20Sopenharmony_ci} 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_cistatic void __qed_get_vport_mstats_addrlen(struct qed_hwfn *p_hwfn, 17148c2ecf20Sopenharmony_ci u32 *p_addr, 17158c2ecf20Sopenharmony_ci u32 *p_len, u16 statistics_bin) 17168c2ecf20Sopenharmony_ci{ 17178c2ecf20Sopenharmony_ci if (IS_PF(p_hwfn->cdev)) { 17188c2ecf20Sopenharmony_ci *p_addr = BAR0_MAP_REG_MSDM_RAM + 17198c2ecf20Sopenharmony_ci MSTORM_QUEUE_STAT_OFFSET(statistics_bin); 17208c2ecf20Sopenharmony_ci *p_len = sizeof(struct eth_mstorm_per_queue_stat); 17218c2ecf20Sopenharmony_ci } else { 17228c2ecf20Sopenharmony_ci struct qed_vf_iov *p_iov = p_hwfn->vf_iov_info; 17238c2ecf20Sopenharmony_ci struct pfvf_acquire_resp_tlv *p_resp = &p_iov->acquire_resp; 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci *p_addr = p_resp->pfdev_info.stats_info.mstats.address; 17268c2ecf20Sopenharmony_ci *p_len = p_resp->pfdev_info.stats_info.mstats.len; 17278c2ecf20Sopenharmony_ci } 17288c2ecf20Sopenharmony_ci} 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_cistatic noinline_for_stack void 17318c2ecf20Sopenharmony_ci__qed_get_vport_mstats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 17328c2ecf20Sopenharmony_ci struct qed_eth_stats *p_stats, u16 statistics_bin) 17338c2ecf20Sopenharmony_ci{ 17348c2ecf20Sopenharmony_ci struct eth_mstorm_per_queue_stat mstats; 17358c2ecf20Sopenharmony_ci u32 mstats_addr = 0, mstats_len = 0; 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_ci __qed_get_vport_mstats_addrlen(p_hwfn, &mstats_addr, &mstats_len, 17388c2ecf20Sopenharmony_ci statistics_bin); 17398c2ecf20Sopenharmony_ci 17408c2ecf20Sopenharmony_ci memset(&mstats, 0, sizeof(mstats)); 17418c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &mstats, mstats_addr, mstats_len); 17428c2ecf20Sopenharmony_ci 17438c2ecf20Sopenharmony_ci p_stats->common.no_buff_discards += 17448c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.no_buff_discard); 17458c2ecf20Sopenharmony_ci p_stats->common.packet_too_big_discard += 17468c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.packet_too_big_discard); 17478c2ecf20Sopenharmony_ci p_stats->common.ttl0_discard += HILO_64_REGPAIR(mstats.ttl0_discard); 17488c2ecf20Sopenharmony_ci p_stats->common.tpa_coalesced_pkts += 17498c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.tpa_coalesced_pkts); 17508c2ecf20Sopenharmony_ci p_stats->common.tpa_coalesced_events += 17518c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.tpa_coalesced_events); 17528c2ecf20Sopenharmony_ci p_stats->common.tpa_aborts_num += 17538c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.tpa_aborts_num); 17548c2ecf20Sopenharmony_ci p_stats->common.tpa_coalesced_bytes += 17558c2ecf20Sopenharmony_ci HILO_64_REGPAIR(mstats.tpa_coalesced_bytes); 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_cistatic noinline_for_stack void 17598c2ecf20Sopenharmony_ci__qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, 17608c2ecf20Sopenharmony_ci struct qed_eth_stats *p_stats) 17618c2ecf20Sopenharmony_ci{ 17628c2ecf20Sopenharmony_ci struct qed_eth_stats_common *p_common = &p_stats->common; 17638c2ecf20Sopenharmony_ci struct port_stats port_stats; 17648c2ecf20Sopenharmony_ci int j; 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ci memset(&port_stats, 0, sizeof(port_stats)); 17678c2ecf20Sopenharmony_ci 17688c2ecf20Sopenharmony_ci qed_memcpy_from(p_hwfn, p_ptt, &port_stats, 17698c2ecf20Sopenharmony_ci p_hwfn->mcp_info->port_addr + 17708c2ecf20Sopenharmony_ci offsetof(struct public_port, stats), 17718c2ecf20Sopenharmony_ci sizeof(port_stats)); 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci p_common->rx_64_byte_packets += port_stats.eth.r64; 17748c2ecf20Sopenharmony_ci p_common->rx_65_to_127_byte_packets += port_stats.eth.r127; 17758c2ecf20Sopenharmony_ci p_common->rx_128_to_255_byte_packets += port_stats.eth.r255; 17768c2ecf20Sopenharmony_ci p_common->rx_256_to_511_byte_packets += port_stats.eth.r511; 17778c2ecf20Sopenharmony_ci p_common->rx_512_to_1023_byte_packets += port_stats.eth.r1023; 17788c2ecf20Sopenharmony_ci p_common->rx_1024_to_1518_byte_packets += port_stats.eth.r1518; 17798c2ecf20Sopenharmony_ci p_common->rx_crc_errors += port_stats.eth.rfcs; 17808c2ecf20Sopenharmony_ci p_common->rx_mac_crtl_frames += port_stats.eth.rxcf; 17818c2ecf20Sopenharmony_ci p_common->rx_pause_frames += port_stats.eth.rxpf; 17828c2ecf20Sopenharmony_ci p_common->rx_pfc_frames += port_stats.eth.rxpp; 17838c2ecf20Sopenharmony_ci p_common->rx_align_errors += port_stats.eth.raln; 17848c2ecf20Sopenharmony_ci p_common->rx_carrier_errors += port_stats.eth.rfcr; 17858c2ecf20Sopenharmony_ci p_common->rx_oversize_packets += port_stats.eth.rovr; 17868c2ecf20Sopenharmony_ci p_common->rx_jabbers += port_stats.eth.rjbr; 17878c2ecf20Sopenharmony_ci p_common->rx_undersize_packets += port_stats.eth.rund; 17888c2ecf20Sopenharmony_ci p_common->rx_fragments += port_stats.eth.rfrg; 17898c2ecf20Sopenharmony_ci p_common->tx_64_byte_packets += port_stats.eth.t64; 17908c2ecf20Sopenharmony_ci p_common->tx_65_to_127_byte_packets += port_stats.eth.t127; 17918c2ecf20Sopenharmony_ci p_common->tx_128_to_255_byte_packets += port_stats.eth.t255; 17928c2ecf20Sopenharmony_ci p_common->tx_256_to_511_byte_packets += port_stats.eth.t511; 17938c2ecf20Sopenharmony_ci p_common->tx_512_to_1023_byte_packets += port_stats.eth.t1023; 17948c2ecf20Sopenharmony_ci p_common->tx_1024_to_1518_byte_packets += port_stats.eth.t1518; 17958c2ecf20Sopenharmony_ci p_common->tx_pause_frames += port_stats.eth.txpf; 17968c2ecf20Sopenharmony_ci p_common->tx_pfc_frames += port_stats.eth.txpp; 17978c2ecf20Sopenharmony_ci p_common->rx_mac_bytes += port_stats.eth.rbyte; 17988c2ecf20Sopenharmony_ci p_common->rx_mac_uc_packets += port_stats.eth.rxuca; 17998c2ecf20Sopenharmony_ci p_common->rx_mac_mc_packets += port_stats.eth.rxmca; 18008c2ecf20Sopenharmony_ci p_common->rx_mac_bc_packets += port_stats.eth.rxbca; 18018c2ecf20Sopenharmony_ci p_common->rx_mac_frames_ok += port_stats.eth.rxpok; 18028c2ecf20Sopenharmony_ci p_common->tx_mac_bytes += port_stats.eth.tbyte; 18038c2ecf20Sopenharmony_ci p_common->tx_mac_uc_packets += port_stats.eth.txuca; 18048c2ecf20Sopenharmony_ci p_common->tx_mac_mc_packets += port_stats.eth.txmca; 18058c2ecf20Sopenharmony_ci p_common->tx_mac_bc_packets += port_stats.eth.txbca; 18068c2ecf20Sopenharmony_ci p_common->tx_mac_ctrl_frames += port_stats.eth.txcf; 18078c2ecf20Sopenharmony_ci for (j = 0; j < 8; j++) { 18088c2ecf20Sopenharmony_ci p_common->brb_truncates += port_stats.brb.brb_truncate[j]; 18098c2ecf20Sopenharmony_ci p_common->brb_discards += port_stats.brb.brb_discard[j]; 18108c2ecf20Sopenharmony_ci } 18118c2ecf20Sopenharmony_ci 18128c2ecf20Sopenharmony_ci if (QED_IS_BB(p_hwfn->cdev)) { 18138c2ecf20Sopenharmony_ci struct qed_eth_stats_bb *p_bb = &p_stats->bb; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci p_bb->rx_1519_to_1522_byte_packets += 18168c2ecf20Sopenharmony_ci port_stats.eth.u0.bb0.r1522; 18178c2ecf20Sopenharmony_ci p_bb->rx_1519_to_2047_byte_packets += 18188c2ecf20Sopenharmony_ci port_stats.eth.u0.bb0.r2047; 18198c2ecf20Sopenharmony_ci p_bb->rx_2048_to_4095_byte_packets += 18208c2ecf20Sopenharmony_ci port_stats.eth.u0.bb0.r4095; 18218c2ecf20Sopenharmony_ci p_bb->rx_4096_to_9216_byte_packets += 18228c2ecf20Sopenharmony_ci port_stats.eth.u0.bb0.r9216; 18238c2ecf20Sopenharmony_ci p_bb->rx_9217_to_16383_byte_packets += 18248c2ecf20Sopenharmony_ci port_stats.eth.u0.bb0.r16383; 18258c2ecf20Sopenharmony_ci p_bb->tx_1519_to_2047_byte_packets += 18268c2ecf20Sopenharmony_ci port_stats.eth.u1.bb1.t2047; 18278c2ecf20Sopenharmony_ci p_bb->tx_2048_to_4095_byte_packets += 18288c2ecf20Sopenharmony_ci port_stats.eth.u1.bb1.t4095; 18298c2ecf20Sopenharmony_ci p_bb->tx_4096_to_9216_byte_packets += 18308c2ecf20Sopenharmony_ci port_stats.eth.u1.bb1.t9216; 18318c2ecf20Sopenharmony_ci p_bb->tx_9217_to_16383_byte_packets += 18328c2ecf20Sopenharmony_ci port_stats.eth.u1.bb1.t16383; 18338c2ecf20Sopenharmony_ci p_bb->tx_lpi_entry_count += port_stats.eth.u2.bb2.tlpiec; 18348c2ecf20Sopenharmony_ci p_bb->tx_total_collisions += port_stats.eth.u2.bb2.tncl; 18358c2ecf20Sopenharmony_ci } else { 18368c2ecf20Sopenharmony_ci struct qed_eth_stats_ah *p_ah = &p_stats->ah; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci p_ah->rx_1519_to_max_byte_packets += 18398c2ecf20Sopenharmony_ci port_stats.eth.u0.ah0.r1519_to_max; 18408c2ecf20Sopenharmony_ci p_ah->tx_1519_to_max_byte_packets = 18418c2ecf20Sopenharmony_ci port_stats.eth.u1.ah1.t1519_to_max; 18428c2ecf20Sopenharmony_ci } 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci p_common->link_change_count = qed_rd(p_hwfn, p_ptt, 18458c2ecf20Sopenharmony_ci p_hwfn->mcp_info->port_addr + 18468c2ecf20Sopenharmony_ci offsetof(struct public_port, 18478c2ecf20Sopenharmony_ci link_change_count)); 18488c2ecf20Sopenharmony_ci} 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_cistatic void __qed_get_vport_stats(struct qed_hwfn *p_hwfn, 18518c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 18528c2ecf20Sopenharmony_ci struct qed_eth_stats *stats, 18538c2ecf20Sopenharmony_ci u16 statistics_bin, bool b_get_port_stats) 18548c2ecf20Sopenharmony_ci{ 18558c2ecf20Sopenharmony_ci __qed_get_vport_mstats(p_hwfn, p_ptt, stats, statistics_bin); 18568c2ecf20Sopenharmony_ci __qed_get_vport_ustats(p_hwfn, p_ptt, stats, statistics_bin); 18578c2ecf20Sopenharmony_ci __qed_get_vport_tstats(p_hwfn, p_ptt, stats, statistics_bin); 18588c2ecf20Sopenharmony_ci __qed_get_vport_pstats(p_hwfn, p_ptt, stats, statistics_bin); 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci if (b_get_port_stats && p_hwfn->mcp_info) 18618c2ecf20Sopenharmony_ci __qed_get_vport_port_stats(p_hwfn, p_ptt, stats); 18628c2ecf20Sopenharmony_ci} 18638c2ecf20Sopenharmony_ci 18648c2ecf20Sopenharmony_cistatic void _qed_get_vport_stats(struct qed_dev *cdev, 18658c2ecf20Sopenharmony_ci struct qed_eth_stats *stats) 18668c2ecf20Sopenharmony_ci{ 18678c2ecf20Sopenharmony_ci u8 fw_vport = 0; 18688c2ecf20Sopenharmony_ci int i; 18698c2ecf20Sopenharmony_ci 18708c2ecf20Sopenharmony_ci memset(stats, 0, sizeof(*stats)); 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 18738c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 18748c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn) 18758c2ecf20Sopenharmony_ci : NULL; 18768c2ecf20Sopenharmony_ci bool b_get_port_stats; 18778c2ecf20Sopenharmony_ci 18788c2ecf20Sopenharmony_ci if (IS_PF(cdev)) { 18798c2ecf20Sopenharmony_ci /* The main vport index is relative first */ 18808c2ecf20Sopenharmony_ci if (qed_fw_vport(p_hwfn, 0, &fw_vport)) { 18818c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "No vport available!\n"); 18828c2ecf20Sopenharmony_ci goto out; 18838c2ecf20Sopenharmony_ci } 18848c2ecf20Sopenharmony_ci } 18858c2ecf20Sopenharmony_ci 18868c2ecf20Sopenharmony_ci if (IS_PF(cdev) && !p_ptt) { 18878c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Failed to acquire ptt\n"); 18888c2ecf20Sopenharmony_ci continue; 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci b_get_port_stats = IS_PF(cdev) && IS_LEAD_HWFN(p_hwfn); 18928c2ecf20Sopenharmony_ci __qed_get_vport_stats(p_hwfn, p_ptt, stats, fw_vport, 18938c2ecf20Sopenharmony_ci b_get_port_stats); 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ciout: 18968c2ecf20Sopenharmony_ci if (IS_PF(cdev) && p_ptt) 18978c2ecf20Sopenharmony_ci qed_ptt_release(p_hwfn, p_ptt); 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci} 19008c2ecf20Sopenharmony_ci 19018c2ecf20Sopenharmony_civoid qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats) 19028c2ecf20Sopenharmony_ci{ 19038c2ecf20Sopenharmony_ci u32 i; 19048c2ecf20Sopenharmony_ci 19058c2ecf20Sopenharmony_ci if (!cdev || cdev->recov_in_prog) { 19068c2ecf20Sopenharmony_ci memset(stats, 0, sizeof(*stats)); 19078c2ecf20Sopenharmony_ci return; 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci 19108c2ecf20Sopenharmony_ci _qed_get_vport_stats(cdev, stats); 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci if (!cdev->reset_stats) 19138c2ecf20Sopenharmony_ci return; 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_ci /* Reduce the statistics baseline */ 19168c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(struct qed_eth_stats) / sizeof(u64); i++) 19178c2ecf20Sopenharmony_ci ((u64 *)stats)[i] -= ((u64 *)cdev->reset_stats)[i]; 19188c2ecf20Sopenharmony_ci} 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci/* zeroes V-PORT specific portion of stats (Port stats remains untouched) */ 19218c2ecf20Sopenharmony_civoid qed_reset_vport_stats(struct qed_dev *cdev) 19228c2ecf20Sopenharmony_ci{ 19238c2ecf20Sopenharmony_ci int i; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 19268c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 19278c2ecf20Sopenharmony_ci struct eth_mstorm_per_queue_stat mstats; 19288c2ecf20Sopenharmony_ci struct eth_ustorm_per_queue_stat ustats; 19298c2ecf20Sopenharmony_ci struct eth_pstorm_per_queue_stat pstats; 19308c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn) 19318c2ecf20Sopenharmony_ci : NULL; 19328c2ecf20Sopenharmony_ci u32 addr = 0, len = 0; 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ci if (IS_PF(cdev) && !p_ptt) { 19358c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "Failed to acquire ptt\n"); 19368c2ecf20Sopenharmony_ci continue; 19378c2ecf20Sopenharmony_ci } 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci memset(&mstats, 0, sizeof(mstats)); 19408c2ecf20Sopenharmony_ci __qed_get_vport_mstats_addrlen(p_hwfn, &addr, &len, 0); 19418c2ecf20Sopenharmony_ci qed_memcpy_to(p_hwfn, p_ptt, addr, &mstats, len); 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci memset(&ustats, 0, sizeof(ustats)); 19448c2ecf20Sopenharmony_ci __qed_get_vport_ustats_addrlen(p_hwfn, &addr, &len, 0); 19458c2ecf20Sopenharmony_ci qed_memcpy_to(p_hwfn, p_ptt, addr, &ustats, len); 19468c2ecf20Sopenharmony_ci 19478c2ecf20Sopenharmony_ci memset(&pstats, 0, sizeof(pstats)); 19488c2ecf20Sopenharmony_ci __qed_get_vport_pstats_addrlen(p_hwfn, &addr, &len, 0); 19498c2ecf20Sopenharmony_ci qed_memcpy_to(p_hwfn, p_ptt, addr, &pstats, len); 19508c2ecf20Sopenharmony_ci 19518c2ecf20Sopenharmony_ci if (IS_PF(cdev)) 19528c2ecf20Sopenharmony_ci qed_ptt_release(p_hwfn, p_ptt); 19538c2ecf20Sopenharmony_ci } 19548c2ecf20Sopenharmony_ci 19558c2ecf20Sopenharmony_ci /* PORT statistics are not necessarily reset, so we need to 19568c2ecf20Sopenharmony_ci * read and create a baseline for future statistics. 19578c2ecf20Sopenharmony_ci * Link change stat is maintained by MFW, return its value as is. 19588c2ecf20Sopenharmony_ci */ 19598c2ecf20Sopenharmony_ci if (!cdev->reset_stats) { 19608c2ecf20Sopenharmony_ci DP_INFO(cdev, "Reset stats not allocated\n"); 19618c2ecf20Sopenharmony_ci } else { 19628c2ecf20Sopenharmony_ci _qed_get_vport_stats(cdev, cdev->reset_stats); 19638c2ecf20Sopenharmony_ci cdev->reset_stats->common.link_change_count = 0; 19648c2ecf20Sopenharmony_ci } 19658c2ecf20Sopenharmony_ci} 19668c2ecf20Sopenharmony_ci 19678c2ecf20Sopenharmony_cistatic enum gft_profile_type 19688c2ecf20Sopenharmony_ciqed_arfs_mode_to_hsi(enum qed_filter_config_mode mode) 19698c2ecf20Sopenharmony_ci{ 19708c2ecf20Sopenharmony_ci if (mode == QED_FILTER_CONFIG_MODE_5_TUPLE) 19718c2ecf20Sopenharmony_ci return GFT_PROFILE_TYPE_4_TUPLE; 19728c2ecf20Sopenharmony_ci if (mode == QED_FILTER_CONFIG_MODE_IP_DEST) 19738c2ecf20Sopenharmony_ci return GFT_PROFILE_TYPE_IP_DST_ADDR; 19748c2ecf20Sopenharmony_ci if (mode == QED_FILTER_CONFIG_MODE_IP_SRC) 19758c2ecf20Sopenharmony_ci return GFT_PROFILE_TYPE_IP_SRC_ADDR; 19768c2ecf20Sopenharmony_ci return GFT_PROFILE_TYPE_L4_DST_PORT; 19778c2ecf20Sopenharmony_ci} 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_civoid qed_arfs_mode_configure(struct qed_hwfn *p_hwfn, 19808c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 19818c2ecf20Sopenharmony_ci struct qed_arfs_config_params *p_cfg_params) 19828c2ecf20Sopenharmony_ci{ 19838c2ecf20Sopenharmony_ci if (test_bit(QED_MF_DISABLE_ARFS, &p_hwfn->cdev->mf_bits)) 19848c2ecf20Sopenharmony_ci return; 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_ci if (p_cfg_params->mode != QED_FILTER_CONFIG_MODE_DISABLE) { 19878c2ecf20Sopenharmony_ci qed_gft_config(p_hwfn, p_ptt, p_hwfn->rel_pf_id, 19888c2ecf20Sopenharmony_ci p_cfg_params->tcp, 19898c2ecf20Sopenharmony_ci p_cfg_params->udp, 19908c2ecf20Sopenharmony_ci p_cfg_params->ipv4, 19918c2ecf20Sopenharmony_ci p_cfg_params->ipv6, 19928c2ecf20Sopenharmony_ci qed_arfs_mode_to_hsi(p_cfg_params->mode)); 19938c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, 19948c2ecf20Sopenharmony_ci QED_MSG_SP, 19958c2ecf20Sopenharmony_ci "Configured Filtering: tcp = %s, udp = %s, ipv4 = %s, ipv6 =%s mode=%08x\n", 19968c2ecf20Sopenharmony_ci p_cfg_params->tcp ? "Enable" : "Disable", 19978c2ecf20Sopenharmony_ci p_cfg_params->udp ? "Enable" : "Disable", 19988c2ecf20Sopenharmony_ci p_cfg_params->ipv4 ? "Enable" : "Disable", 19998c2ecf20Sopenharmony_ci p_cfg_params->ipv6 ? "Enable" : "Disable", 20008c2ecf20Sopenharmony_ci (u32)p_cfg_params->mode); 20018c2ecf20Sopenharmony_ci } else { 20028c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, "Disabled Filtering\n"); 20038c2ecf20Sopenharmony_ci qed_gft_disable(p_hwfn, p_ptt, p_hwfn->rel_pf_id); 20048c2ecf20Sopenharmony_ci } 20058c2ecf20Sopenharmony_ci} 20068c2ecf20Sopenharmony_ci 20078c2ecf20Sopenharmony_ciint 20088c2ecf20Sopenharmony_ciqed_configure_rfs_ntuple_filter(struct qed_hwfn *p_hwfn, 20098c2ecf20Sopenharmony_ci struct qed_spq_comp_cb *p_cb, 20108c2ecf20Sopenharmony_ci struct qed_ntuple_filter_params *p_params) 20118c2ecf20Sopenharmony_ci{ 20128c2ecf20Sopenharmony_ci struct rx_update_gft_filter_data *p_ramrod = NULL; 20138c2ecf20Sopenharmony_ci struct qed_spq_entry *p_ent = NULL; 20148c2ecf20Sopenharmony_ci struct qed_sp_init_data init_data; 20158c2ecf20Sopenharmony_ci u16 abs_rx_q_id = 0; 20168c2ecf20Sopenharmony_ci u8 abs_vport_id = 0; 20178c2ecf20Sopenharmony_ci int rc = -EINVAL; 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci /* Get SPQ entry */ 20208c2ecf20Sopenharmony_ci memset(&init_data, 0, sizeof(init_data)); 20218c2ecf20Sopenharmony_ci init_data.cid = qed_spq_get_cid(p_hwfn); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci if (p_cb) { 20268c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_CB; 20278c2ecf20Sopenharmony_ci init_data.p_comp_data = p_cb; 20288c2ecf20Sopenharmony_ci } else { 20298c2ecf20Sopenharmony_ci init_data.comp_mode = QED_SPQ_MODE_EBLOCK; 20308c2ecf20Sopenharmony_ci } 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci rc = qed_sp_init_request(p_hwfn, &p_ent, 20338c2ecf20Sopenharmony_ci ETH_RAMROD_GFT_UPDATE_FILTER, 20348c2ecf20Sopenharmony_ci PROTOCOLID_ETH, &init_data); 20358c2ecf20Sopenharmony_ci if (rc) 20368c2ecf20Sopenharmony_ci return rc; 20378c2ecf20Sopenharmony_ci 20388c2ecf20Sopenharmony_ci p_ramrod = &p_ent->ramrod.rx_update_gft; 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_ci DMA_REGPAIR_LE(p_ramrod->pkt_hdr_addr, p_params->addr); 20418c2ecf20Sopenharmony_ci p_ramrod->pkt_hdr_length = cpu_to_le16(p_params->length); 20428c2ecf20Sopenharmony_ci 20438c2ecf20Sopenharmony_ci if (p_params->b_is_drop) { 20448c2ecf20Sopenharmony_ci p_ramrod->vport_id = cpu_to_le16(ETH_GFT_TRASHCAN_VPORT); 20458c2ecf20Sopenharmony_ci } else { 20468c2ecf20Sopenharmony_ci rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); 20478c2ecf20Sopenharmony_ci if (rc) 20488c2ecf20Sopenharmony_ci goto err; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci if (p_params->qid != QED_RFS_NTUPLE_QID_RSS) { 20518c2ecf20Sopenharmony_ci rc = qed_fw_l2_queue(p_hwfn, p_params->qid, 20528c2ecf20Sopenharmony_ci &abs_rx_q_id); 20538c2ecf20Sopenharmony_ci if (rc) 20548c2ecf20Sopenharmony_ci goto err; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci p_ramrod->rx_qid_valid = 1; 20578c2ecf20Sopenharmony_ci p_ramrod->rx_qid = cpu_to_le16(abs_rx_q_id); 20588c2ecf20Sopenharmony_ci } 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci p_ramrod->vport_id = cpu_to_le16((u16)abs_vport_id); 20618c2ecf20Sopenharmony_ci } 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci p_ramrod->flow_id_valid = 0; 20648c2ecf20Sopenharmony_ci p_ramrod->flow_id = 0; 20658c2ecf20Sopenharmony_ci p_ramrod->filter_action = p_params->b_is_add ? GFT_ADD_FILTER 20668c2ecf20Sopenharmony_ci : GFT_DELETE_FILTER; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, QED_MSG_SP, 20698c2ecf20Sopenharmony_ci "V[%0x], Q[%04x] - %s filter from 0x%llx [length %04xb]\n", 20708c2ecf20Sopenharmony_ci abs_vport_id, abs_rx_q_id, 20718c2ecf20Sopenharmony_ci p_params->b_is_add ? "Adding" : "Removing", 20728c2ecf20Sopenharmony_ci (u64)p_params->addr, p_params->length); 20738c2ecf20Sopenharmony_ci 20748c2ecf20Sopenharmony_ci return qed_spq_post(p_hwfn, p_ent, NULL); 20758c2ecf20Sopenharmony_ci 20768c2ecf20Sopenharmony_cierr: 20778c2ecf20Sopenharmony_ci qed_sp_destroy_request(p_hwfn, p_ent); 20788c2ecf20Sopenharmony_ci return rc; 20798c2ecf20Sopenharmony_ci} 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_ciint qed_get_rxq_coalesce(struct qed_hwfn *p_hwfn, 20828c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 20838c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, u16 *p_rx_coal) 20848c2ecf20Sopenharmony_ci{ 20858c2ecf20Sopenharmony_ci u32 coalesce, address, is_valid; 20868c2ecf20Sopenharmony_ci struct cau_sb_entry sb_entry; 20878c2ecf20Sopenharmony_ci u8 timer_res; 20888c2ecf20Sopenharmony_ci int rc; 20898c2ecf20Sopenharmony_ci 20908c2ecf20Sopenharmony_ci rc = qed_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY + 20918c2ecf20Sopenharmony_ci p_cid->sb_igu_id * sizeof(u64), 20928c2ecf20Sopenharmony_ci (u64)(uintptr_t)&sb_entry, 2, NULL); 20938c2ecf20Sopenharmony_ci if (rc) { 20948c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc); 20958c2ecf20Sopenharmony_ci return rc; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci timer_res = GET_FIELD(le32_to_cpu(sb_entry.params), 20998c2ecf20Sopenharmony_ci CAU_SB_ENTRY_TIMER_RES0); 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci address = BAR0_MAP_REG_USDM_RAM + 21028c2ecf20Sopenharmony_ci USTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id); 21038c2ecf20Sopenharmony_ci coalesce = qed_rd(p_hwfn, p_ptt, address); 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci is_valid = GET_FIELD(coalesce, COALESCING_TIMESET_VALID); 21068c2ecf20Sopenharmony_ci if (!is_valid) 21078c2ecf20Sopenharmony_ci return -EINVAL; 21088c2ecf20Sopenharmony_ci 21098c2ecf20Sopenharmony_ci coalesce = GET_FIELD(coalesce, COALESCING_TIMESET_TIMESET); 21108c2ecf20Sopenharmony_ci *p_rx_coal = (u16)(coalesce << timer_res); 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci return 0; 21138c2ecf20Sopenharmony_ci} 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ciint qed_get_txq_coalesce(struct qed_hwfn *p_hwfn, 21168c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt, 21178c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid, u16 *p_tx_coal) 21188c2ecf20Sopenharmony_ci{ 21198c2ecf20Sopenharmony_ci u32 coalesce, address, is_valid; 21208c2ecf20Sopenharmony_ci struct cau_sb_entry sb_entry; 21218c2ecf20Sopenharmony_ci u8 timer_res; 21228c2ecf20Sopenharmony_ci int rc; 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci rc = qed_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY + 21258c2ecf20Sopenharmony_ci p_cid->sb_igu_id * sizeof(u64), 21268c2ecf20Sopenharmony_ci (u64)(uintptr_t)&sb_entry, 2, NULL); 21278c2ecf20Sopenharmony_ci if (rc) { 21288c2ecf20Sopenharmony_ci DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc); 21298c2ecf20Sopenharmony_ci return rc; 21308c2ecf20Sopenharmony_ci } 21318c2ecf20Sopenharmony_ci 21328c2ecf20Sopenharmony_ci timer_res = GET_FIELD(le32_to_cpu(sb_entry.params), 21338c2ecf20Sopenharmony_ci CAU_SB_ENTRY_TIMER_RES1); 21348c2ecf20Sopenharmony_ci 21358c2ecf20Sopenharmony_ci address = BAR0_MAP_REG_XSDM_RAM + 21368c2ecf20Sopenharmony_ci XSTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id); 21378c2ecf20Sopenharmony_ci coalesce = qed_rd(p_hwfn, p_ptt, address); 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci is_valid = GET_FIELD(coalesce, COALESCING_TIMESET_VALID); 21408c2ecf20Sopenharmony_ci if (!is_valid) 21418c2ecf20Sopenharmony_ci return -EINVAL; 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci coalesce = GET_FIELD(coalesce, COALESCING_TIMESET_TIMESET); 21448c2ecf20Sopenharmony_ci *p_tx_coal = (u16)(coalesce << timer_res); 21458c2ecf20Sopenharmony_ci 21468c2ecf20Sopenharmony_ci return 0; 21478c2ecf20Sopenharmony_ci} 21488c2ecf20Sopenharmony_ci 21498c2ecf20Sopenharmony_ciint qed_get_queue_coalesce(struct qed_hwfn *p_hwfn, u16 *p_coal, void *handle) 21508c2ecf20Sopenharmony_ci{ 21518c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid = handle; 21528c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt; 21538c2ecf20Sopenharmony_ci int rc = 0; 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci if (IS_VF(p_hwfn->cdev)) { 21568c2ecf20Sopenharmony_ci rc = qed_vf_pf_get_coalesce(p_hwfn, p_coal, p_cid); 21578c2ecf20Sopenharmony_ci if (rc) 21588c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n"); 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci return rc; 21618c2ecf20Sopenharmony_ci } 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci p_ptt = qed_ptt_acquire(p_hwfn); 21648c2ecf20Sopenharmony_ci if (!p_ptt) 21658c2ecf20Sopenharmony_ci return -EAGAIN; 21668c2ecf20Sopenharmony_ci 21678c2ecf20Sopenharmony_ci if (p_cid->b_is_rx) { 21688c2ecf20Sopenharmony_ci rc = qed_get_rxq_coalesce(p_hwfn, p_ptt, p_cid, p_coal); 21698c2ecf20Sopenharmony_ci if (rc) 21708c2ecf20Sopenharmony_ci goto out; 21718c2ecf20Sopenharmony_ci } else { 21728c2ecf20Sopenharmony_ci rc = qed_get_txq_coalesce(p_hwfn, p_ptt, p_cid, p_coal); 21738c2ecf20Sopenharmony_ci if (rc) 21748c2ecf20Sopenharmony_ci goto out; 21758c2ecf20Sopenharmony_ci } 21768c2ecf20Sopenharmony_ci 21778c2ecf20Sopenharmony_ciout: 21788c2ecf20Sopenharmony_ci qed_ptt_release(p_hwfn, p_ptt); 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci return rc; 21818c2ecf20Sopenharmony_ci} 21828c2ecf20Sopenharmony_ci 21838c2ecf20Sopenharmony_cistatic int qed_fill_eth_dev_info(struct qed_dev *cdev, 21848c2ecf20Sopenharmony_ci struct qed_dev_eth_info *info) 21858c2ecf20Sopenharmony_ci{ 21868c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 21878c2ecf20Sopenharmony_ci int i; 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci memset(info, 0, sizeof(*info)); 21908c2ecf20Sopenharmony_ci 21918c2ecf20Sopenharmony_ci if (IS_PF(cdev)) { 21928c2ecf20Sopenharmony_ci int max_vf_vlan_filters = 0; 21938c2ecf20Sopenharmony_ci int max_vf_mac_filters = 0; 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci info->num_tc = p_hwfn->hw_info.num_hw_tc; 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci if (cdev->int_params.out.int_mode == QED_INT_MODE_MSIX) { 21988c2ecf20Sopenharmony_ci u16 num_queues = 0; 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci /* Since the feature controls only queue-zones, 22018c2ecf20Sopenharmony_ci * make sure we have the contexts [rx, xdp, tcs] to 22028c2ecf20Sopenharmony_ci * match. 22038c2ecf20Sopenharmony_ci */ 22048c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 22058c2ecf20Sopenharmony_ci struct qed_hwfn *hwfn = &cdev->hwfns[i]; 22068c2ecf20Sopenharmony_ci u16 l2_queues = (u16)FEAT_NUM(hwfn, 22078c2ecf20Sopenharmony_ci QED_PF_L2_QUE); 22088c2ecf20Sopenharmony_ci u16 cids; 22098c2ecf20Sopenharmony_ci 22108c2ecf20Sopenharmony_ci cids = hwfn->pf_params.eth_pf_params.num_cons; 22118c2ecf20Sopenharmony_ci cids /= (2 + info->num_tc); 22128c2ecf20Sopenharmony_ci num_queues += min_t(u16, l2_queues, cids); 22138c2ecf20Sopenharmony_ci } 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci /* queues might theoretically be >256, but interrupts' 22168c2ecf20Sopenharmony_ci * upper-limit guarantes that it would fit in a u8. 22178c2ecf20Sopenharmony_ci */ 22188c2ecf20Sopenharmony_ci if (cdev->int_params.fp_msix_cnt) { 22198c2ecf20Sopenharmony_ci u8 irqs = cdev->int_params.fp_msix_cnt; 22208c2ecf20Sopenharmony_ci 22218c2ecf20Sopenharmony_ci info->num_queues = (u8)min_t(u16, 22228c2ecf20Sopenharmony_ci num_queues, irqs); 22238c2ecf20Sopenharmony_ci } 22248c2ecf20Sopenharmony_ci } else { 22258c2ecf20Sopenharmony_ci info->num_queues = cdev->num_hwfns; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci 22288c2ecf20Sopenharmony_ci if (IS_QED_SRIOV(cdev)) { 22298c2ecf20Sopenharmony_ci max_vf_vlan_filters = cdev->p_iov_info->total_vfs * 22308c2ecf20Sopenharmony_ci QED_ETH_VF_NUM_VLAN_FILTERS; 22318c2ecf20Sopenharmony_ci max_vf_mac_filters = cdev->p_iov_info->total_vfs * 22328c2ecf20Sopenharmony_ci QED_ETH_VF_NUM_MAC_FILTERS; 22338c2ecf20Sopenharmony_ci } 22348c2ecf20Sopenharmony_ci info->num_vlan_filters = RESC_NUM(QED_LEADING_HWFN(cdev), 22358c2ecf20Sopenharmony_ci QED_VLAN) - 22368c2ecf20Sopenharmony_ci max_vf_vlan_filters; 22378c2ecf20Sopenharmony_ci info->num_mac_filters = RESC_NUM(QED_LEADING_HWFN(cdev), 22388c2ecf20Sopenharmony_ci QED_MAC) - 22398c2ecf20Sopenharmony_ci max_vf_mac_filters; 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci ether_addr_copy(info->port_mac, 22428c2ecf20Sopenharmony_ci cdev->hwfns[0].hw_info.hw_mac_addr); 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_ci info->xdp_supported = true; 22458c2ecf20Sopenharmony_ci } else { 22468c2ecf20Sopenharmony_ci u16 total_cids = 0; 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci info->num_tc = 1; 22498c2ecf20Sopenharmony_ci 22508c2ecf20Sopenharmony_ci /* Determine queues & XDP support */ 22518c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 22528c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 22538c2ecf20Sopenharmony_ci u8 queues, cids; 22548c2ecf20Sopenharmony_ci 22558c2ecf20Sopenharmony_ci qed_vf_get_num_cids(p_hwfn, &cids); 22568c2ecf20Sopenharmony_ci qed_vf_get_num_rxqs(p_hwfn, &queues); 22578c2ecf20Sopenharmony_ci info->num_queues += queues; 22588c2ecf20Sopenharmony_ci total_cids += cids; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci /* Enable VF XDP in case PF guarntees sufficient connections */ 22628c2ecf20Sopenharmony_ci if (total_cids >= info->num_queues * 3) 22638c2ecf20Sopenharmony_ci info->xdp_supported = true; 22648c2ecf20Sopenharmony_ci 22658c2ecf20Sopenharmony_ci qed_vf_get_num_vlan_filters(&cdev->hwfns[0], 22668c2ecf20Sopenharmony_ci (u8 *)&info->num_vlan_filters); 22678c2ecf20Sopenharmony_ci qed_vf_get_num_mac_filters(&cdev->hwfns[0], 22688c2ecf20Sopenharmony_ci (u8 *)&info->num_mac_filters); 22698c2ecf20Sopenharmony_ci qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac); 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi; 22728c2ecf20Sopenharmony_ci } 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci qed_fill_dev_info(cdev, &info->common); 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_ci if (IS_VF(cdev)) 22778c2ecf20Sopenharmony_ci eth_zero_addr(info->common.hw_mac); 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci return 0; 22808c2ecf20Sopenharmony_ci} 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_cistatic void qed_register_eth_ops(struct qed_dev *cdev, 22838c2ecf20Sopenharmony_ci struct qed_eth_cb_ops *ops, void *cookie) 22848c2ecf20Sopenharmony_ci{ 22858c2ecf20Sopenharmony_ci cdev->protocol_ops.eth = ops; 22868c2ecf20Sopenharmony_ci cdev->ops_cookie = cookie; 22878c2ecf20Sopenharmony_ci 22888c2ecf20Sopenharmony_ci /* For VF, we start bulletin reading */ 22898c2ecf20Sopenharmony_ci if (IS_VF(cdev)) 22908c2ecf20Sopenharmony_ci qed_vf_start_iov_wq(cdev); 22918c2ecf20Sopenharmony_ci} 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_cistatic bool qed_check_mac(struct qed_dev *cdev, u8 *mac) 22948c2ecf20Sopenharmony_ci{ 22958c2ecf20Sopenharmony_ci if (IS_PF(cdev)) 22968c2ecf20Sopenharmony_ci return true; 22978c2ecf20Sopenharmony_ci 22988c2ecf20Sopenharmony_ci return qed_vf_check_mac(&cdev->hwfns[0], mac); 22998c2ecf20Sopenharmony_ci} 23008c2ecf20Sopenharmony_ci 23018c2ecf20Sopenharmony_cistatic int qed_start_vport(struct qed_dev *cdev, 23028c2ecf20Sopenharmony_ci struct qed_start_vport_params *params) 23038c2ecf20Sopenharmony_ci{ 23048c2ecf20Sopenharmony_ci int rc, i; 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 23078c2ecf20Sopenharmony_ci struct qed_sp_vport_start_params start = { 0 }; 23088c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci start.tpa_mode = params->gro_enable ? QED_TPA_MODE_GRO : 23118c2ecf20Sopenharmony_ci QED_TPA_MODE_NONE; 23128c2ecf20Sopenharmony_ci start.remove_inner_vlan = params->remove_inner_vlan; 23138c2ecf20Sopenharmony_ci start.only_untagged = true; /* untagged only */ 23148c2ecf20Sopenharmony_ci start.drop_ttl0 = params->drop_ttl0; 23158c2ecf20Sopenharmony_ci start.opaque_fid = p_hwfn->hw_info.opaque_fid; 23168c2ecf20Sopenharmony_ci start.concrete_fid = p_hwfn->hw_info.concrete_fid; 23178c2ecf20Sopenharmony_ci start.handle_ptp_pkts = params->handle_ptp_pkts; 23188c2ecf20Sopenharmony_ci start.vport_id = params->vport_id; 23198c2ecf20Sopenharmony_ci start.max_buffers_per_cqe = 16; 23208c2ecf20Sopenharmony_ci start.mtu = params->mtu; 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci rc = qed_sp_vport_start(p_hwfn, &start); 23238c2ecf20Sopenharmony_ci if (rc) { 23248c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to start VPORT\n"); 23258c2ecf20Sopenharmony_ci return rc; 23268c2ecf20Sopenharmony_ci } 23278c2ecf20Sopenharmony_ci 23288c2ecf20Sopenharmony_ci rc = qed_hw_start_fastpath(p_hwfn); 23298c2ecf20Sopenharmony_ci if (rc) { 23308c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to start VPORT fastpath\n"); 23318c2ecf20Sopenharmony_ci return rc; 23328c2ecf20Sopenharmony_ci } 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), 23358c2ecf20Sopenharmony_ci "Started V-PORT %d with MTU %d\n", 23368c2ecf20Sopenharmony_ci start.vport_id, start.mtu); 23378c2ecf20Sopenharmony_ci } 23388c2ecf20Sopenharmony_ci 23398c2ecf20Sopenharmony_ci if (params->clear_stats) 23408c2ecf20Sopenharmony_ci qed_reset_vport_stats(cdev); 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci return 0; 23438c2ecf20Sopenharmony_ci} 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_cistatic int qed_stop_vport(struct qed_dev *cdev, u8 vport_id) 23468c2ecf20Sopenharmony_ci{ 23478c2ecf20Sopenharmony_ci int rc, i; 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 23508c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci rc = qed_sp_vport_stop(p_hwfn, 23538c2ecf20Sopenharmony_ci p_hwfn->hw_info.opaque_fid, vport_id); 23548c2ecf20Sopenharmony_ci 23558c2ecf20Sopenharmony_ci if (rc) { 23568c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to stop VPORT\n"); 23578c2ecf20Sopenharmony_ci return rc; 23588c2ecf20Sopenharmony_ci } 23598c2ecf20Sopenharmony_ci } 23608c2ecf20Sopenharmony_ci return 0; 23618c2ecf20Sopenharmony_ci} 23628c2ecf20Sopenharmony_ci 23638c2ecf20Sopenharmony_cistatic int qed_update_vport_rss(struct qed_dev *cdev, 23648c2ecf20Sopenharmony_ci struct qed_update_vport_rss_params *input, 23658c2ecf20Sopenharmony_ci struct qed_rss_params *rss) 23668c2ecf20Sopenharmony_ci{ 23678c2ecf20Sopenharmony_ci int i, fn; 23688c2ecf20Sopenharmony_ci 23698c2ecf20Sopenharmony_ci /* Update configuration with what's correct regardless of CMT */ 23708c2ecf20Sopenharmony_ci rss->update_rss_config = 1; 23718c2ecf20Sopenharmony_ci rss->rss_enable = 1; 23728c2ecf20Sopenharmony_ci rss->update_rss_capabilities = 1; 23738c2ecf20Sopenharmony_ci rss->update_rss_ind_table = 1; 23748c2ecf20Sopenharmony_ci rss->update_rss_key = 1; 23758c2ecf20Sopenharmony_ci rss->rss_caps = input->rss_caps; 23768c2ecf20Sopenharmony_ci memcpy(rss->rss_key, input->rss_key, QED_RSS_KEY_SIZE * sizeof(u32)); 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci /* In regular scenario, we'd simply need to take input handlers. 23798c2ecf20Sopenharmony_ci * But in CMT, we'd have to split the handlers according to the 23808c2ecf20Sopenharmony_ci * engine they were configured on. We'd then have to understand 23818c2ecf20Sopenharmony_ci * whether RSS is really required, since 2-queues on CMT doesn't 23828c2ecf20Sopenharmony_ci * require RSS. 23838c2ecf20Sopenharmony_ci */ 23848c2ecf20Sopenharmony_ci if (cdev->num_hwfns == 1) { 23858c2ecf20Sopenharmony_ci memcpy(rss->rss_ind_table, 23868c2ecf20Sopenharmony_ci input->rss_ind_table, 23878c2ecf20Sopenharmony_ci QED_RSS_IND_TABLE_SIZE * sizeof(void *)); 23888c2ecf20Sopenharmony_ci rss->rss_table_size_log = 7; 23898c2ecf20Sopenharmony_ci return 0; 23908c2ecf20Sopenharmony_ci } 23918c2ecf20Sopenharmony_ci 23928c2ecf20Sopenharmony_ci /* Start by copying the non-spcific information to the 2nd copy */ 23938c2ecf20Sopenharmony_ci memcpy(&rss[1], &rss[0], sizeof(struct qed_rss_params)); 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_ci /* CMT should be round-robin */ 23968c2ecf20Sopenharmony_ci for (i = 0; i < QED_RSS_IND_TABLE_SIZE; i++) { 23978c2ecf20Sopenharmony_ci struct qed_queue_cid *cid = input->rss_ind_table[i]; 23988c2ecf20Sopenharmony_ci struct qed_rss_params *t_rss; 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci if (cid->p_owner == QED_LEADING_HWFN(cdev)) 24018c2ecf20Sopenharmony_ci t_rss = &rss[0]; 24028c2ecf20Sopenharmony_ci else 24038c2ecf20Sopenharmony_ci t_rss = &rss[1]; 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci t_rss->rss_ind_table[i / cdev->num_hwfns] = cid; 24068c2ecf20Sopenharmony_ci } 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_ci /* Make sure RSS is actually required */ 24098c2ecf20Sopenharmony_ci for_each_hwfn(cdev, fn) { 24108c2ecf20Sopenharmony_ci for (i = 1; i < QED_RSS_IND_TABLE_SIZE / cdev->num_hwfns; i++) { 24118c2ecf20Sopenharmony_ci if (rss[fn].rss_ind_table[i] != 24128c2ecf20Sopenharmony_ci rss[fn].rss_ind_table[0]) 24138c2ecf20Sopenharmony_ci break; 24148c2ecf20Sopenharmony_ci } 24158c2ecf20Sopenharmony_ci if (i == QED_RSS_IND_TABLE_SIZE / cdev->num_hwfns) { 24168c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, NETIF_MSG_IFUP, 24178c2ecf20Sopenharmony_ci "CMT - 1 queue per-hwfn; Disabling RSS\n"); 24188c2ecf20Sopenharmony_ci return -EINVAL; 24198c2ecf20Sopenharmony_ci } 24208c2ecf20Sopenharmony_ci rss[fn].rss_table_size_log = 6; 24218c2ecf20Sopenharmony_ci } 24228c2ecf20Sopenharmony_ci 24238c2ecf20Sopenharmony_ci return 0; 24248c2ecf20Sopenharmony_ci} 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_cistatic int qed_update_vport(struct qed_dev *cdev, 24278c2ecf20Sopenharmony_ci struct qed_update_vport_params *params) 24288c2ecf20Sopenharmony_ci{ 24298c2ecf20Sopenharmony_ci struct qed_sp_vport_update_params sp_params; 24308c2ecf20Sopenharmony_ci struct qed_rss_params *rss; 24318c2ecf20Sopenharmony_ci int rc = 0, i; 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci if (!cdev) 24348c2ecf20Sopenharmony_ci return -ENODEV; 24358c2ecf20Sopenharmony_ci 24368c2ecf20Sopenharmony_ci rss = vzalloc(array_size(sizeof(*rss), cdev->num_hwfns)); 24378c2ecf20Sopenharmony_ci if (!rss) 24388c2ecf20Sopenharmony_ci return -ENOMEM; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci memset(&sp_params, 0, sizeof(sp_params)); 24418c2ecf20Sopenharmony_ci 24428c2ecf20Sopenharmony_ci /* Translate protocol params into sp params */ 24438c2ecf20Sopenharmony_ci sp_params.vport_id = params->vport_id; 24448c2ecf20Sopenharmony_ci sp_params.update_vport_active_rx_flg = params->update_vport_active_flg; 24458c2ecf20Sopenharmony_ci sp_params.update_vport_active_tx_flg = params->update_vport_active_flg; 24468c2ecf20Sopenharmony_ci sp_params.vport_active_rx_flg = params->vport_active_flg; 24478c2ecf20Sopenharmony_ci sp_params.vport_active_tx_flg = params->vport_active_flg; 24488c2ecf20Sopenharmony_ci sp_params.update_tx_switching_flg = params->update_tx_switching_flg; 24498c2ecf20Sopenharmony_ci sp_params.tx_switching_flg = params->tx_switching_flg; 24508c2ecf20Sopenharmony_ci sp_params.accept_any_vlan = params->accept_any_vlan; 24518c2ecf20Sopenharmony_ci sp_params.update_accept_any_vlan_flg = 24528c2ecf20Sopenharmony_ci params->update_accept_any_vlan_flg; 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci /* Prepare the RSS configuration */ 24558c2ecf20Sopenharmony_ci if (params->update_rss_flg) 24568c2ecf20Sopenharmony_ci if (qed_update_vport_rss(cdev, ¶ms->rss_params, rss)) 24578c2ecf20Sopenharmony_ci params->update_rss_flg = 0; 24588c2ecf20Sopenharmony_ci 24598c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 24608c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 24618c2ecf20Sopenharmony_ci 24628c2ecf20Sopenharmony_ci if (params->update_rss_flg) 24638c2ecf20Sopenharmony_ci sp_params.rss_params = &rss[i]; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci sp_params.opaque_fid = p_hwfn->hw_info.opaque_fid; 24668c2ecf20Sopenharmony_ci rc = qed_sp_vport_update(p_hwfn, &sp_params, 24678c2ecf20Sopenharmony_ci QED_SPQ_MODE_EBLOCK, 24688c2ecf20Sopenharmony_ci NULL); 24698c2ecf20Sopenharmony_ci if (rc) { 24708c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to update VPORT\n"); 24718c2ecf20Sopenharmony_ci goto out; 24728c2ecf20Sopenharmony_ci } 24738c2ecf20Sopenharmony_ci 24748c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), 24758c2ecf20Sopenharmony_ci "Updated V-PORT %d: active_flag %d [update %d]\n", 24768c2ecf20Sopenharmony_ci params->vport_id, params->vport_active_flg, 24778c2ecf20Sopenharmony_ci params->update_vport_active_flg); 24788c2ecf20Sopenharmony_ci } 24798c2ecf20Sopenharmony_ci 24808c2ecf20Sopenharmony_ciout: 24818c2ecf20Sopenharmony_ci vfree(rss); 24828c2ecf20Sopenharmony_ci return rc; 24838c2ecf20Sopenharmony_ci} 24848c2ecf20Sopenharmony_ci 24858c2ecf20Sopenharmony_cistatic int qed_start_rxq(struct qed_dev *cdev, 24868c2ecf20Sopenharmony_ci u8 rss_num, 24878c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 24888c2ecf20Sopenharmony_ci u16 bd_max_bytes, 24898c2ecf20Sopenharmony_ci dma_addr_t bd_chain_phys_addr, 24908c2ecf20Sopenharmony_ci dma_addr_t cqe_pbl_addr, 24918c2ecf20Sopenharmony_ci u16 cqe_pbl_size, 24928c2ecf20Sopenharmony_ci struct qed_rxq_start_ret_params *ret_params) 24938c2ecf20Sopenharmony_ci{ 24948c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn; 24958c2ecf20Sopenharmony_ci int rc, hwfn_index; 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci hwfn_index = rss_num % cdev->num_hwfns; 24988c2ecf20Sopenharmony_ci p_hwfn = &cdev->hwfns[hwfn_index]; 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci p_params->queue_id = p_params->queue_id / cdev->num_hwfns; 25018c2ecf20Sopenharmony_ci p_params->stats_id = p_params->vport_id; 25028c2ecf20Sopenharmony_ci 25038c2ecf20Sopenharmony_ci rc = qed_eth_rx_queue_start(p_hwfn, 25048c2ecf20Sopenharmony_ci p_hwfn->hw_info.opaque_fid, 25058c2ecf20Sopenharmony_ci p_params, 25068c2ecf20Sopenharmony_ci bd_max_bytes, 25078c2ecf20Sopenharmony_ci bd_chain_phys_addr, 25088c2ecf20Sopenharmony_ci cqe_pbl_addr, cqe_pbl_size, ret_params); 25098c2ecf20Sopenharmony_ci if (rc) { 25108c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to start RXQ#%d\n", p_params->queue_id); 25118c2ecf20Sopenharmony_ci return rc; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), 25158c2ecf20Sopenharmony_ci "Started RX-Q %d [rss_num %d] on V-PORT %d and SB igu %d\n", 25168c2ecf20Sopenharmony_ci p_params->queue_id, rss_num, p_params->vport_id, 25178c2ecf20Sopenharmony_ci p_params->p_sb->igu_sb_id); 25188c2ecf20Sopenharmony_ci 25198c2ecf20Sopenharmony_ci return 0; 25208c2ecf20Sopenharmony_ci} 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_cistatic int qed_stop_rxq(struct qed_dev *cdev, u8 rss_id, void *handle) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci int rc, hwfn_index; 25258c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn; 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci hwfn_index = rss_id % cdev->num_hwfns; 25288c2ecf20Sopenharmony_ci p_hwfn = &cdev->hwfns[hwfn_index]; 25298c2ecf20Sopenharmony_ci 25308c2ecf20Sopenharmony_ci rc = qed_eth_rx_queue_stop(p_hwfn, handle, false, false); 25318c2ecf20Sopenharmony_ci if (rc) { 25328c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to stop RXQ#%02x\n", rss_id); 25338c2ecf20Sopenharmony_ci return rc; 25348c2ecf20Sopenharmony_ci } 25358c2ecf20Sopenharmony_ci 25368c2ecf20Sopenharmony_ci return 0; 25378c2ecf20Sopenharmony_ci} 25388c2ecf20Sopenharmony_ci 25398c2ecf20Sopenharmony_cistatic int qed_start_txq(struct qed_dev *cdev, 25408c2ecf20Sopenharmony_ci u8 rss_num, 25418c2ecf20Sopenharmony_ci struct qed_queue_start_common_params *p_params, 25428c2ecf20Sopenharmony_ci dma_addr_t pbl_addr, 25438c2ecf20Sopenharmony_ci u16 pbl_size, 25448c2ecf20Sopenharmony_ci struct qed_txq_start_ret_params *ret_params) 25458c2ecf20Sopenharmony_ci{ 25468c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn; 25478c2ecf20Sopenharmony_ci int rc, hwfn_index; 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci hwfn_index = rss_num % cdev->num_hwfns; 25508c2ecf20Sopenharmony_ci p_hwfn = &cdev->hwfns[hwfn_index]; 25518c2ecf20Sopenharmony_ci p_params->queue_id = p_params->queue_id / cdev->num_hwfns; 25528c2ecf20Sopenharmony_ci p_params->stats_id = p_params->vport_id; 25538c2ecf20Sopenharmony_ci 25548c2ecf20Sopenharmony_ci rc = qed_eth_tx_queue_start(p_hwfn, 25558c2ecf20Sopenharmony_ci p_hwfn->hw_info.opaque_fid, 25568c2ecf20Sopenharmony_ci p_params, p_params->tc, 25578c2ecf20Sopenharmony_ci pbl_addr, pbl_size, ret_params); 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci if (rc) { 25608c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to start TXQ#%d\n", p_params->queue_id); 25618c2ecf20Sopenharmony_ci return rc; 25628c2ecf20Sopenharmony_ci } 25638c2ecf20Sopenharmony_ci 25648c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), 25658c2ecf20Sopenharmony_ci "Started TX-Q %d [rss_num %d] on V-PORT %d and SB igu %d\n", 25668c2ecf20Sopenharmony_ci p_params->queue_id, rss_num, p_params->vport_id, 25678c2ecf20Sopenharmony_ci p_params->p_sb->igu_sb_id); 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci return 0; 25708c2ecf20Sopenharmony_ci} 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ci#define QED_HW_STOP_RETRY_LIMIT (10) 25738c2ecf20Sopenharmony_cistatic int qed_fastpath_stop(struct qed_dev *cdev) 25748c2ecf20Sopenharmony_ci{ 25758c2ecf20Sopenharmony_ci int rc; 25768c2ecf20Sopenharmony_ci 25778c2ecf20Sopenharmony_ci rc = qed_hw_stop_fastpath(cdev); 25788c2ecf20Sopenharmony_ci if (rc) { 25798c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to stop Fastpath\n"); 25808c2ecf20Sopenharmony_ci return rc; 25818c2ecf20Sopenharmony_ci } 25828c2ecf20Sopenharmony_ci 25838c2ecf20Sopenharmony_ci return 0; 25848c2ecf20Sopenharmony_ci} 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_cistatic int qed_stop_txq(struct qed_dev *cdev, u8 rss_id, void *handle) 25878c2ecf20Sopenharmony_ci{ 25888c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn; 25898c2ecf20Sopenharmony_ci int rc, hwfn_index; 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci hwfn_index = rss_id % cdev->num_hwfns; 25928c2ecf20Sopenharmony_ci p_hwfn = &cdev->hwfns[hwfn_index]; 25938c2ecf20Sopenharmony_ci 25948c2ecf20Sopenharmony_ci rc = qed_eth_tx_queue_stop(p_hwfn, handle); 25958c2ecf20Sopenharmony_ci if (rc) { 25968c2ecf20Sopenharmony_ci DP_ERR(cdev, "Failed to stop TXQ#%02x\n", rss_id); 25978c2ecf20Sopenharmony_ci return rc; 25988c2ecf20Sopenharmony_ci } 25998c2ecf20Sopenharmony_ci 26008c2ecf20Sopenharmony_ci return 0; 26018c2ecf20Sopenharmony_ci} 26028c2ecf20Sopenharmony_ci 26038c2ecf20Sopenharmony_cistatic int qed_tunn_configure(struct qed_dev *cdev, 26048c2ecf20Sopenharmony_ci struct qed_tunn_params *tunn_params) 26058c2ecf20Sopenharmony_ci{ 26068c2ecf20Sopenharmony_ci struct qed_tunnel_info tunn_info; 26078c2ecf20Sopenharmony_ci int i, rc; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci memset(&tunn_info, 0, sizeof(tunn_info)); 26108c2ecf20Sopenharmony_ci if (tunn_params->update_vxlan_port) { 26118c2ecf20Sopenharmony_ci tunn_info.vxlan_port.b_update_port = true; 26128c2ecf20Sopenharmony_ci tunn_info.vxlan_port.port = tunn_params->vxlan_port; 26138c2ecf20Sopenharmony_ci } 26148c2ecf20Sopenharmony_ci 26158c2ecf20Sopenharmony_ci if (tunn_params->update_geneve_port) { 26168c2ecf20Sopenharmony_ci tunn_info.geneve_port.b_update_port = true; 26178c2ecf20Sopenharmony_ci tunn_info.geneve_port.port = tunn_params->geneve_port; 26188c2ecf20Sopenharmony_ci } 26198c2ecf20Sopenharmony_ci 26208c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 26218c2ecf20Sopenharmony_ci struct qed_hwfn *hwfn = &cdev->hwfns[i]; 26228c2ecf20Sopenharmony_ci struct qed_ptt *p_ptt; 26238c2ecf20Sopenharmony_ci struct qed_tunnel_info *tun; 26248c2ecf20Sopenharmony_ci 26258c2ecf20Sopenharmony_ci tun = &hwfn->cdev->tunnel; 26268c2ecf20Sopenharmony_ci if (IS_PF(cdev)) { 26278c2ecf20Sopenharmony_ci p_ptt = qed_ptt_acquire(hwfn); 26288c2ecf20Sopenharmony_ci if (!p_ptt) 26298c2ecf20Sopenharmony_ci return -EAGAIN; 26308c2ecf20Sopenharmony_ci } else { 26318c2ecf20Sopenharmony_ci p_ptt = NULL; 26328c2ecf20Sopenharmony_ci } 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_ci rc = qed_sp_pf_update_tunn_cfg(hwfn, p_ptt, &tunn_info, 26358c2ecf20Sopenharmony_ci QED_SPQ_MODE_EBLOCK, NULL); 26368c2ecf20Sopenharmony_ci if (rc) { 26378c2ecf20Sopenharmony_ci if (IS_PF(cdev)) 26388c2ecf20Sopenharmony_ci qed_ptt_release(hwfn, p_ptt); 26398c2ecf20Sopenharmony_ci return rc; 26408c2ecf20Sopenharmony_ci } 26418c2ecf20Sopenharmony_ci 26428c2ecf20Sopenharmony_ci if (IS_PF_SRIOV(hwfn)) { 26438c2ecf20Sopenharmony_ci u16 vxlan_port, geneve_port; 26448c2ecf20Sopenharmony_ci int j; 26458c2ecf20Sopenharmony_ci 26468c2ecf20Sopenharmony_ci vxlan_port = tun->vxlan_port.port; 26478c2ecf20Sopenharmony_ci geneve_port = tun->geneve_port.port; 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci qed_for_each_vf(hwfn, j) { 26508c2ecf20Sopenharmony_ci qed_iov_bulletin_set_udp_ports(hwfn, j, 26518c2ecf20Sopenharmony_ci vxlan_port, 26528c2ecf20Sopenharmony_ci geneve_port); 26538c2ecf20Sopenharmony_ci } 26548c2ecf20Sopenharmony_ci 26558c2ecf20Sopenharmony_ci qed_schedule_iov(hwfn, QED_IOV_WQ_BULLETIN_UPDATE_FLAG); 26568c2ecf20Sopenharmony_ci } 26578c2ecf20Sopenharmony_ci if (IS_PF(cdev)) 26588c2ecf20Sopenharmony_ci qed_ptt_release(hwfn, p_ptt); 26598c2ecf20Sopenharmony_ci } 26608c2ecf20Sopenharmony_ci 26618c2ecf20Sopenharmony_ci return 0; 26628c2ecf20Sopenharmony_ci} 26638c2ecf20Sopenharmony_ci 26648c2ecf20Sopenharmony_cistatic int qed_configure_filter_rx_mode(struct qed_dev *cdev, 26658c2ecf20Sopenharmony_ci enum qed_filter_rx_mode_type type) 26668c2ecf20Sopenharmony_ci{ 26678c2ecf20Sopenharmony_ci struct qed_filter_accept_flags accept_flags; 26688c2ecf20Sopenharmony_ci 26698c2ecf20Sopenharmony_ci memset(&accept_flags, 0, sizeof(accept_flags)); 26708c2ecf20Sopenharmony_ci 26718c2ecf20Sopenharmony_ci accept_flags.update_rx_mode_config = 1; 26728c2ecf20Sopenharmony_ci accept_flags.update_tx_mode_config = 1; 26738c2ecf20Sopenharmony_ci accept_flags.rx_accept_filter = QED_ACCEPT_UCAST_MATCHED | 26748c2ecf20Sopenharmony_ci QED_ACCEPT_MCAST_MATCHED | 26758c2ecf20Sopenharmony_ci QED_ACCEPT_BCAST; 26768c2ecf20Sopenharmony_ci accept_flags.tx_accept_filter = QED_ACCEPT_UCAST_MATCHED | 26778c2ecf20Sopenharmony_ci QED_ACCEPT_MCAST_MATCHED | 26788c2ecf20Sopenharmony_ci QED_ACCEPT_BCAST; 26798c2ecf20Sopenharmony_ci 26808c2ecf20Sopenharmony_ci if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) { 26818c2ecf20Sopenharmony_ci accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED | 26828c2ecf20Sopenharmony_ci QED_ACCEPT_MCAST_UNMATCHED; 26838c2ecf20Sopenharmony_ci accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED | 26848c2ecf20Sopenharmony_ci QED_ACCEPT_MCAST_UNMATCHED; 26858c2ecf20Sopenharmony_ci } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) { 26868c2ecf20Sopenharmony_ci accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; 26878c2ecf20Sopenharmony_ci accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; 26888c2ecf20Sopenharmony_ci } 26898c2ecf20Sopenharmony_ci 26908c2ecf20Sopenharmony_ci return qed_filter_accept_cmd(cdev, 0, accept_flags, false, false, 26918c2ecf20Sopenharmony_ci QED_SPQ_MODE_CB, NULL); 26928c2ecf20Sopenharmony_ci} 26938c2ecf20Sopenharmony_ci 26948c2ecf20Sopenharmony_cistatic int qed_configure_filter_ucast(struct qed_dev *cdev, 26958c2ecf20Sopenharmony_ci struct qed_filter_ucast_params *params) 26968c2ecf20Sopenharmony_ci{ 26978c2ecf20Sopenharmony_ci struct qed_filter_ucast ucast; 26988c2ecf20Sopenharmony_ci 26998c2ecf20Sopenharmony_ci if (!params->vlan_valid && !params->mac_valid) { 27008c2ecf20Sopenharmony_ci DP_NOTICE(cdev, 27018c2ecf20Sopenharmony_ci "Tried configuring a unicast filter, but both MAC and VLAN are not set\n"); 27028c2ecf20Sopenharmony_ci return -EINVAL; 27038c2ecf20Sopenharmony_ci } 27048c2ecf20Sopenharmony_ci 27058c2ecf20Sopenharmony_ci memset(&ucast, 0, sizeof(ucast)); 27068c2ecf20Sopenharmony_ci switch (params->type) { 27078c2ecf20Sopenharmony_ci case QED_FILTER_XCAST_TYPE_ADD: 27088c2ecf20Sopenharmony_ci ucast.opcode = QED_FILTER_ADD; 27098c2ecf20Sopenharmony_ci break; 27108c2ecf20Sopenharmony_ci case QED_FILTER_XCAST_TYPE_DEL: 27118c2ecf20Sopenharmony_ci ucast.opcode = QED_FILTER_REMOVE; 27128c2ecf20Sopenharmony_ci break; 27138c2ecf20Sopenharmony_ci case QED_FILTER_XCAST_TYPE_REPLACE: 27148c2ecf20Sopenharmony_ci ucast.opcode = QED_FILTER_REPLACE; 27158c2ecf20Sopenharmony_ci break; 27168c2ecf20Sopenharmony_ci default: 27178c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Unknown unicast filter type %d\n", 27188c2ecf20Sopenharmony_ci params->type); 27198c2ecf20Sopenharmony_ci } 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci if (params->vlan_valid && params->mac_valid) { 27228c2ecf20Sopenharmony_ci ucast.type = QED_FILTER_MAC_VLAN; 27238c2ecf20Sopenharmony_ci ether_addr_copy(ucast.mac, params->mac); 27248c2ecf20Sopenharmony_ci ucast.vlan = params->vlan; 27258c2ecf20Sopenharmony_ci } else if (params->mac_valid) { 27268c2ecf20Sopenharmony_ci ucast.type = QED_FILTER_MAC; 27278c2ecf20Sopenharmony_ci ether_addr_copy(ucast.mac, params->mac); 27288c2ecf20Sopenharmony_ci } else { 27298c2ecf20Sopenharmony_ci ucast.type = QED_FILTER_VLAN; 27308c2ecf20Sopenharmony_ci ucast.vlan = params->vlan; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci ucast.is_rx_filter = true; 27348c2ecf20Sopenharmony_ci ucast.is_tx_filter = true; 27358c2ecf20Sopenharmony_ci 27368c2ecf20Sopenharmony_ci return qed_filter_ucast_cmd(cdev, &ucast, QED_SPQ_MODE_CB, NULL); 27378c2ecf20Sopenharmony_ci} 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_cistatic int qed_configure_filter_mcast(struct qed_dev *cdev, 27408c2ecf20Sopenharmony_ci struct qed_filter_mcast_params *params) 27418c2ecf20Sopenharmony_ci{ 27428c2ecf20Sopenharmony_ci struct qed_filter_mcast mcast; 27438c2ecf20Sopenharmony_ci int i; 27448c2ecf20Sopenharmony_ci 27458c2ecf20Sopenharmony_ci memset(&mcast, 0, sizeof(mcast)); 27468c2ecf20Sopenharmony_ci switch (params->type) { 27478c2ecf20Sopenharmony_ci case QED_FILTER_XCAST_TYPE_ADD: 27488c2ecf20Sopenharmony_ci mcast.opcode = QED_FILTER_ADD; 27498c2ecf20Sopenharmony_ci break; 27508c2ecf20Sopenharmony_ci case QED_FILTER_XCAST_TYPE_DEL: 27518c2ecf20Sopenharmony_ci mcast.opcode = QED_FILTER_REMOVE; 27528c2ecf20Sopenharmony_ci break; 27538c2ecf20Sopenharmony_ci default: 27548c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Unknown multicast filter type %d\n", 27558c2ecf20Sopenharmony_ci params->type); 27568c2ecf20Sopenharmony_ci } 27578c2ecf20Sopenharmony_ci 27588c2ecf20Sopenharmony_ci mcast.num_mc_addrs = params->num; 27598c2ecf20Sopenharmony_ci for (i = 0; i < mcast.num_mc_addrs; i++) 27608c2ecf20Sopenharmony_ci ether_addr_copy(mcast.mac[i], params->mac[i]); 27618c2ecf20Sopenharmony_ci 27628c2ecf20Sopenharmony_ci return qed_filter_mcast_cmd(cdev, &mcast, QED_SPQ_MODE_CB, NULL); 27638c2ecf20Sopenharmony_ci} 27648c2ecf20Sopenharmony_ci 27658c2ecf20Sopenharmony_cistatic int qed_configure_filter(struct qed_dev *cdev, 27668c2ecf20Sopenharmony_ci struct qed_filter_params *params) 27678c2ecf20Sopenharmony_ci{ 27688c2ecf20Sopenharmony_ci enum qed_filter_rx_mode_type accept_flags; 27698c2ecf20Sopenharmony_ci 27708c2ecf20Sopenharmony_ci switch (params->type) { 27718c2ecf20Sopenharmony_ci case QED_FILTER_TYPE_UCAST: 27728c2ecf20Sopenharmony_ci return qed_configure_filter_ucast(cdev, ¶ms->filter.ucast); 27738c2ecf20Sopenharmony_ci case QED_FILTER_TYPE_MCAST: 27748c2ecf20Sopenharmony_ci return qed_configure_filter_mcast(cdev, ¶ms->filter.mcast); 27758c2ecf20Sopenharmony_ci case QED_FILTER_TYPE_RX_MODE: 27768c2ecf20Sopenharmony_ci accept_flags = params->filter.accept_flags; 27778c2ecf20Sopenharmony_ci return qed_configure_filter_rx_mode(cdev, accept_flags); 27788c2ecf20Sopenharmony_ci default: 27798c2ecf20Sopenharmony_ci DP_NOTICE(cdev, "Unknown filter type %d\n", (int)params->type); 27808c2ecf20Sopenharmony_ci return -EINVAL; 27818c2ecf20Sopenharmony_ci } 27828c2ecf20Sopenharmony_ci} 27838c2ecf20Sopenharmony_ci 27848c2ecf20Sopenharmony_cistatic int qed_configure_arfs_searcher(struct qed_dev *cdev, 27858c2ecf20Sopenharmony_ci enum qed_filter_config_mode mode) 27868c2ecf20Sopenharmony_ci{ 27878c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 27888c2ecf20Sopenharmony_ci struct qed_arfs_config_params arfs_config_params; 27898c2ecf20Sopenharmony_ci 27908c2ecf20Sopenharmony_ci memset(&arfs_config_params, 0, sizeof(arfs_config_params)); 27918c2ecf20Sopenharmony_ci arfs_config_params.tcp = true; 27928c2ecf20Sopenharmony_ci arfs_config_params.udp = true; 27938c2ecf20Sopenharmony_ci arfs_config_params.ipv4 = true; 27948c2ecf20Sopenharmony_ci arfs_config_params.ipv6 = true; 27958c2ecf20Sopenharmony_ci arfs_config_params.mode = mode; 27968c2ecf20Sopenharmony_ci qed_arfs_mode_configure(p_hwfn, p_hwfn->p_arfs_ptt, 27978c2ecf20Sopenharmony_ci &arfs_config_params); 27988c2ecf20Sopenharmony_ci return 0; 27998c2ecf20Sopenharmony_ci} 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_cistatic void 28028c2ecf20Sopenharmony_ciqed_arfs_sp_response_handler(struct qed_hwfn *p_hwfn, 28038c2ecf20Sopenharmony_ci void *cookie, 28048c2ecf20Sopenharmony_ci union event_ring_data *data, u8 fw_return_code) 28058c2ecf20Sopenharmony_ci{ 28068c2ecf20Sopenharmony_ci struct qed_common_cb_ops *op = p_hwfn->cdev->protocol_ops.common; 28078c2ecf20Sopenharmony_ci void *dev = p_hwfn->cdev->ops_cookie; 28088c2ecf20Sopenharmony_ci 28098c2ecf20Sopenharmony_ci op->arfs_filter_op(dev, cookie, fw_return_code); 28108c2ecf20Sopenharmony_ci} 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_cistatic int 28138c2ecf20Sopenharmony_ciqed_ntuple_arfs_filter_config(struct qed_dev *cdev, 28148c2ecf20Sopenharmony_ci void *cookie, 28158c2ecf20Sopenharmony_ci struct qed_ntuple_filter_params *params) 28168c2ecf20Sopenharmony_ci{ 28178c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev); 28188c2ecf20Sopenharmony_ci struct qed_spq_comp_cb cb; 28198c2ecf20Sopenharmony_ci int rc = -EINVAL; 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci cb.function = qed_arfs_sp_response_handler; 28228c2ecf20Sopenharmony_ci cb.cookie = cookie; 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci if (params->b_is_vf) { 28258c2ecf20Sopenharmony_ci if (!qed_iov_is_valid_vfid(p_hwfn, params->vf_id, false, 28268c2ecf20Sopenharmony_ci false)) { 28278c2ecf20Sopenharmony_ci DP_INFO(p_hwfn, "vfid 0x%02x is out of bounds\n", 28288c2ecf20Sopenharmony_ci params->vf_id); 28298c2ecf20Sopenharmony_ci return rc; 28308c2ecf20Sopenharmony_ci } 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci params->vport_id = params->vf_id + 1; 28338c2ecf20Sopenharmony_ci params->qid = QED_RFS_NTUPLE_QID_RSS; 28348c2ecf20Sopenharmony_ci } 28358c2ecf20Sopenharmony_ci 28368c2ecf20Sopenharmony_ci rc = qed_configure_rfs_ntuple_filter(p_hwfn, &cb, params); 28378c2ecf20Sopenharmony_ci if (rc) 28388c2ecf20Sopenharmony_ci DP_NOTICE(p_hwfn, 28398c2ecf20Sopenharmony_ci "Failed to issue a-RFS filter configuration\n"); 28408c2ecf20Sopenharmony_ci else 28418c2ecf20Sopenharmony_ci DP_VERBOSE(p_hwfn, NETIF_MSG_DRV, 28428c2ecf20Sopenharmony_ci "Successfully issued a-RFS filter configuration\n"); 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci return rc; 28458c2ecf20Sopenharmony_ci} 28468c2ecf20Sopenharmony_ci 28478c2ecf20Sopenharmony_cistatic int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle) 28488c2ecf20Sopenharmony_ci{ 28498c2ecf20Sopenharmony_ci struct qed_queue_cid *p_cid = handle; 28508c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn; 28518c2ecf20Sopenharmony_ci int rc; 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci p_hwfn = p_cid->p_owner; 28548c2ecf20Sopenharmony_ci rc = qed_get_queue_coalesce(p_hwfn, coal, handle); 28558c2ecf20Sopenharmony_ci if (rc) 28568c2ecf20Sopenharmony_ci DP_VERBOSE(cdev, QED_MSG_DEBUG, 28578c2ecf20Sopenharmony_ci "Unable to read queue coalescing\n"); 28588c2ecf20Sopenharmony_ci 28598c2ecf20Sopenharmony_ci return rc; 28608c2ecf20Sopenharmony_ci} 28618c2ecf20Sopenharmony_ci 28628c2ecf20Sopenharmony_cistatic int qed_fp_cqe_completion(struct qed_dev *dev, 28638c2ecf20Sopenharmony_ci u8 rss_id, struct eth_slow_path_rx_cqe *cqe) 28648c2ecf20Sopenharmony_ci{ 28658c2ecf20Sopenharmony_ci return qed_eth_cqe_completion(&dev->hwfns[rss_id % dev->num_hwfns], 28668c2ecf20Sopenharmony_ci cqe); 28678c2ecf20Sopenharmony_ci} 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_cistatic int qed_req_bulletin_update_mac(struct qed_dev *cdev, u8 *mac) 28708c2ecf20Sopenharmony_ci{ 28718c2ecf20Sopenharmony_ci int i, ret; 28728c2ecf20Sopenharmony_ci 28738c2ecf20Sopenharmony_ci if (IS_PF(cdev)) 28748c2ecf20Sopenharmony_ci return 0; 28758c2ecf20Sopenharmony_ci 28768c2ecf20Sopenharmony_ci for_each_hwfn(cdev, i) { 28778c2ecf20Sopenharmony_ci struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci ret = qed_vf_pf_bulletin_update_mac(p_hwfn, mac); 28808c2ecf20Sopenharmony_ci if (ret) 28818c2ecf20Sopenharmony_ci return ret; 28828c2ecf20Sopenharmony_ci } 28838c2ecf20Sopenharmony_ci 28848c2ecf20Sopenharmony_ci return 0; 28858c2ecf20Sopenharmony_ci} 28868c2ecf20Sopenharmony_ci 28878c2ecf20Sopenharmony_cistatic const struct qed_eth_ops qed_eth_ops_pass = { 28888c2ecf20Sopenharmony_ci .common = &qed_common_ops_pass, 28898c2ecf20Sopenharmony_ci#ifdef CONFIG_QED_SRIOV 28908c2ecf20Sopenharmony_ci .iov = &qed_iov_ops_pass, 28918c2ecf20Sopenharmony_ci#endif 28928c2ecf20Sopenharmony_ci#ifdef CONFIG_DCB 28938c2ecf20Sopenharmony_ci .dcb = &qed_dcbnl_ops_pass, 28948c2ecf20Sopenharmony_ci#endif 28958c2ecf20Sopenharmony_ci .ptp = &qed_ptp_ops_pass, 28968c2ecf20Sopenharmony_ci .fill_dev_info = &qed_fill_eth_dev_info, 28978c2ecf20Sopenharmony_ci .register_ops = &qed_register_eth_ops, 28988c2ecf20Sopenharmony_ci .check_mac = &qed_check_mac, 28998c2ecf20Sopenharmony_ci .vport_start = &qed_start_vport, 29008c2ecf20Sopenharmony_ci .vport_stop = &qed_stop_vport, 29018c2ecf20Sopenharmony_ci .vport_update = &qed_update_vport, 29028c2ecf20Sopenharmony_ci .q_rx_start = &qed_start_rxq, 29038c2ecf20Sopenharmony_ci .q_rx_stop = &qed_stop_rxq, 29048c2ecf20Sopenharmony_ci .q_tx_start = &qed_start_txq, 29058c2ecf20Sopenharmony_ci .q_tx_stop = &qed_stop_txq, 29068c2ecf20Sopenharmony_ci .filter_config = &qed_configure_filter, 29078c2ecf20Sopenharmony_ci .fastpath_stop = &qed_fastpath_stop, 29088c2ecf20Sopenharmony_ci .eth_cqe_completion = &qed_fp_cqe_completion, 29098c2ecf20Sopenharmony_ci .get_vport_stats = &qed_get_vport_stats, 29108c2ecf20Sopenharmony_ci .tunn_config = &qed_tunn_configure, 29118c2ecf20Sopenharmony_ci .ntuple_filter_config = &qed_ntuple_arfs_filter_config, 29128c2ecf20Sopenharmony_ci .configure_arfs_searcher = &qed_configure_arfs_searcher, 29138c2ecf20Sopenharmony_ci .get_coalesce = &qed_get_coalesce, 29148c2ecf20Sopenharmony_ci .req_bulletin_update_mac = &qed_req_bulletin_update_mac, 29158c2ecf20Sopenharmony_ci}; 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ciconst struct qed_eth_ops *qed_get_eth_ops(void) 29188c2ecf20Sopenharmony_ci{ 29198c2ecf20Sopenharmony_ci return &qed_eth_ops_pass; 29208c2ecf20Sopenharmony_ci} 29218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(qed_get_eth_ops); 29228c2ecf20Sopenharmony_ci 29238c2ecf20Sopenharmony_civoid qed_put_eth_ops(void) 29248c2ecf20Sopenharmony_ci{ 29258c2ecf20Sopenharmony_ci /* TODO - reference count for module? */ 29268c2ecf20Sopenharmony_ci} 29278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(qed_put_eth_ops); 2928