X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fqede%2Fbase%2Fecore_l2.c;h=8b9817eb2879089ee685a2bbc1c0af7a062861ce;hb=45a49cc7e7a589d268e362ee275c399a6640708a;hp=3071b4613644cdfdb7c819eb92cac85a595ceec9;hpb=30ecf67308f2e0477f60e66edf789b72e239c759;p=dpdk.git diff --git a/drivers/net/qede/base/ecore_l2.c b/drivers/net/qede/base/ecore_l2.c index 3071b46136..8b9817eb28 100644 --- a/drivers/net/qede/base/ecore_l2.c +++ b/drivers/net/qede/base/ecore_l2.c @@ -1,9 +1,7 @@ -/* - * Copyright (c) 2016 QLogic Corporation. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (c) 2016 - 2018 Cavium Inc. * All rights reserved. - * www.qlogic.com - * - * See LICENSE.qede_pmd for copyright and licensing details. + * www.cavium.com */ #include "bcm_osal.h" @@ -77,7 +75,8 @@ enum _ecore_status_t ecore_l2_alloc(struct ecore_hwfn *p_hwfn) } #ifdef CONFIG_ECORE_LOCK_ALLOC - OSAL_MUTEX_ALLOC(p_hwfn, &p_l2_info->lock); + if (OSAL_MUTEX_ALLOC(p_hwfn, &p_l2_info->lock)) + return ECORE_NOMEM; #endif return ECORE_SUCCESS; @@ -110,6 +109,7 @@ void ecore_l2_free(struct ecore_hwfn *p_hwfn) break; OSAL_VFREE(p_hwfn->p_dev, p_hwfn->p_l2_info->pp_qid_usage[i]); + p_hwfn->p_l2_info->pp_qid_usage[i] = OSAL_NULL; } #ifdef CONFIG_ECORE_LOCK_ALLOC @@ -119,6 +119,7 @@ void ecore_l2_free(struct ecore_hwfn *p_hwfn) #endif OSAL_VFREE(p_hwfn->p_dev, p_hwfn->p_l2_info->pp_qid_usage); + p_hwfn->p_l2_info->pp_qid_usage = OSAL_NULL; out_l2_info: OSAL_VFREE(p_hwfn->p_dev, p_hwfn->p_l2_info); @@ -196,6 +197,7 @@ static struct ecore_queue_cid * _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, u16 opaque_fid, u32 cid, struct ecore_queue_start_common_params *p_params, + bool b_is_rx, struct ecore_queue_cid_vf_params *p_vf_params) { struct ecore_queue_cid *p_cid; @@ -214,6 +216,7 @@ _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, p_cid->rel.queue_id = p_params->queue_id; p_cid->rel.stats_id = p_params->stats_id; p_cid->sb_igu_id = p_params->p_sb->igu_sb_id; + p_cid->b_is_rx = b_is_rx; p_cid->sb_idx = p_params->sb_idx; /* Fill-in bits related to VFs' queues if information was provided */ @@ -233,7 +236,7 @@ _ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, } /* Calculate the engine-absolute indices of the resources. - * The would guarantee they're valid later on. + * This would guarantee they're valid later on. * In some cases [SBs] we already have the right values. */ rc = ecore_fw_vport(p_hwfn, p_cid->rel.vport_id, &p_cid->abs.vport_id); @@ -287,6 +290,7 @@ fail: struct ecore_queue_cid * ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, u16 opaque_fid, struct ecore_queue_start_common_params *p_params, + bool b_is_rx, struct ecore_queue_cid_vf_params *p_vf_params) { struct ecore_queue_cid *p_cid; @@ -321,7 +325,7 @@ ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, u16 opaque_fid, } p_cid = _ecore_eth_queue_to_cid(p_hwfn, opaque_fid, cid, - p_params, p_vf_params); + p_params, b_is_rx, p_vf_params); if ((p_cid == OSAL_NULL) && IS_PF(p_hwfn->p_dev) && !b_legacy_vf) _ecore_cxt_release_cid(p_hwfn, cid, vfid); @@ -330,9 +334,11 @@ ecore_eth_queue_to_cid(struct ecore_hwfn *p_hwfn, u16 opaque_fid, static struct ecore_queue_cid * ecore_eth_queue_to_cid_pf(struct ecore_hwfn *p_hwfn, u16 opaque_fid, + bool b_is_rx, struct ecore_queue_start_common_params *p_params) { - return ecore_eth_queue_to_cid(p_hwfn, opaque_fid, p_params, OSAL_NULL); + return ecore_eth_queue_to_cid(p_hwfn, opaque_fid, p_params, b_is_rx, + OSAL_NULL); } enum _ecore_status_t @@ -342,6 +348,7 @@ ecore_sp_eth_vport_start(struct ecore_hwfn *p_hwfn, struct vport_start_ramrod_data *p_ramrod = OSAL_NULL; struct ecore_spq_entry *p_ent = OSAL_NULL; struct ecore_sp_init_data init_data; + struct eth_vport_tpa_param *p_tpa; u16 rx_mode = 0, tx_err = 0; u8 abs_vport_id = 0; enum _ecore_status_t rc = ECORE_NOTIMPL; @@ -366,8 +373,8 @@ ecore_sp_eth_vport_start(struct ecore_hwfn *p_hwfn, p_ramrod->vport_id = abs_vport_id; p_ramrod->mtu = OSAL_CPU_TO_LE16(p_params->mtu); - p_ramrod->inner_vlan_removal_en = p_params->remove_inner_vlan; p_ramrod->handle_ptp_pkts = p_params->handle_ptp_pkts; + p_ramrod->inner_vlan_removal_en = p_params->remove_inner_vlan; p_ramrod->drop_ttl0_en = p_params->drop_ttl0; p_ramrod->untagged = p_params->only_untagged; p_ramrod->zero_placement_offset = p_params->zero_placement_offset; @@ -402,22 +409,22 @@ ecore_sp_eth_vport_start(struct ecore_hwfn *p_hwfn, p_ramrod->tx_err_behav.values = OSAL_CPU_TO_LE16(tx_err); /* TPA related fields */ - OSAL_MEMSET(&p_ramrod->tpa_param, 0, - sizeof(struct eth_vport_tpa_param)); - p_ramrod->tpa_param.max_buff_num = p_params->max_buffers_per_cqe; + p_tpa = &p_ramrod->tpa_param; + OSAL_MEMSET(p_tpa, 0, sizeof(struct eth_vport_tpa_param)); + p_tpa->max_buff_num = p_params->max_buffers_per_cqe; switch (p_params->tpa_mode) { case ECORE_TPA_MODE_GRO: - p_ramrod->tpa_param.tpa_max_aggs_num = ETH_TPA_MAX_AGGS_NUM; - p_ramrod->tpa_param.tpa_max_size = (u16)-1; - p_ramrod->tpa_param.tpa_min_size_to_cont = p_params->mtu / 2; - p_ramrod->tpa_param.tpa_min_size_to_start = p_params->mtu / 2; - p_ramrod->tpa_param.tpa_ipv4_en_flg = 1; - p_ramrod->tpa_param.tpa_ipv6_en_flg = 1; - p_ramrod->tpa_param.tpa_ipv4_tunn_en_flg = 1; - p_ramrod->tpa_param.tpa_ipv6_tunn_en_flg = 1; - p_ramrod->tpa_param.tpa_pkt_split_flg = 1; - p_ramrod->tpa_param.tpa_gro_consistent_flg = 1; + p_tpa->tpa_max_aggs_num = ETH_TPA_MAX_AGGS_NUM; + p_tpa->tpa_max_size = (u16)-1; + p_tpa->tpa_min_size_to_cont = p_params->mtu / 2; + p_tpa->tpa_min_size_to_start = p_params->mtu / 2; + p_tpa->tpa_ipv4_en_flg = 1; + p_tpa->tpa_ipv6_en_flg = 1; + p_tpa->tpa_ipv4_tunn_en_flg = 1; + p_tpa->tpa_ipv6_tunn_en_flg = 1; + p_tpa->tpa_pkt_split_flg = 1; + p_tpa->tpa_gro_consistent_flg = 1; break; default: break; @@ -459,6 +466,7 @@ ecore_sp_vport_update_rss(struct ecore_hwfn *p_hwfn, struct ecore_rss_params *p_rss) { struct eth_vport_rss_config *p_config; + u16 capabilities = 0; int i, table_size; enum _ecore_status_t rc = ECORE_SUCCESS; @@ -485,26 +493,26 @@ ecore_sp_vport_update_rss(struct ecore_hwfn *p_hwfn, p_config->capabilities = 0; - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV4_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV4)); - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV6_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV6)); - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV4_TCP_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV4_TCP)); - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV6_TCP_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV6_TCP)); - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV4_UDP_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV4_UDP)); - SET_FIELD(p_config->capabilities, + SET_FIELD(capabilities, ETH_VPORT_RSS_CONFIG_IPV6_UDP_CAPABILITY, !!(p_rss->rss_caps & ECORE_RSS_IPV6_UDP)); p_config->tbl_size = p_rss->rss_table_size_log; - p_config->capabilities = OSAL_CPU_TO_LE16(p_config->capabilities); + p_config->capabilities = OSAL_CPU_TO_LE16(capabilities); DP_VERBOSE(p_hwfn, ECORE_MSG_IFUP, "update rss flag %d, rss_mode = %d, update_caps = %d, capabilities = %d, update_ind = %d, update_rss_key = %d\n", @@ -600,6 +608,9 @@ ecore_sp_update_accept_mode(struct ecore_hwfn *p_hwfn, SET_FIELD(state, ETH_VPORT_RX_MODE_BCAST_ACCEPT_ALL, !!(accept_filter & ECORE_ACCEPT_BCAST)); + SET_FIELD(state, ETH_VPORT_RX_MODE_ACCEPT_ANY_VNI, + !!(accept_filter & ECORE_ACCEPT_ANY_VNI)); + p_ramrod->rx_mode.state = OSAL_CPU_TO_LE16(state); DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "vport[%02x] p_ramrod->rx_mode.state = 0x%x\n", @@ -636,6 +647,7 @@ ecore_sp_vport_update_sge_tpa(struct vport_update_ramrod_data *p_ramrod, struct ecore_sge_tpa_params *p_params) { struct eth_vport_tpa_param *p_tpa; + u16 val; if (!p_params) { p_ramrod->common.update_tpa_param_flg = 0; @@ -657,9 +669,12 @@ ecore_sp_vport_update_sge_tpa(struct vport_update_ramrod_data *p_ramrod, p_tpa->tpa_hdr_data_split_flg = p_params->tpa_hdr_data_split_flg; p_tpa->tpa_gro_consistent_flg = p_params->tpa_gro_consistent_flg; p_tpa->tpa_max_aggs_num = p_params->tpa_max_aggs_num; - p_tpa->tpa_max_size = p_params->tpa_max_size; - p_tpa->tpa_min_size_to_start = p_params->tpa_min_size_to_start; - p_tpa->tpa_min_size_to_cont = p_params->tpa_min_size_to_cont; + val = p_params->tpa_max_size; + p_tpa->tpa_max_size = OSAL_CPU_TO_LE16(val); + val = p_params->tpa_min_size_to_start; + p_tpa->tpa_min_size_to_start = OSAL_CPU_TO_LE16(val); + val = p_params->tpa_min_size_to_cont; + p_tpa->tpa_min_size_to_cont = OSAL_CPU_TO_LE16(val); } static void @@ -676,7 +691,7 @@ ecore_sp_update_mcast_bin(struct vport_update_ramrod_data *p_ramrod, p_ramrod->common.update_approx_mcast_flg = 1; for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { - u32 *p_bins = (u32 *)p_params->bins; + u32 *p_bins = p_params->bins; p_ramrod->approx_mcast.bins[i] = OSAL_CPU_TO_LE32(p_bins[i]); } @@ -771,6 +786,11 @@ ecore_sp_vport_update(struct ecore_hwfn *p_hwfn, return rc; } + if (p_params->update_ctl_frame_check) { + p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en; + p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en; + } + /* Update mcast bins for VFs, PF doesn't use this functionality */ ecore_sp_update_mcast_bin(p_ramrod, p_params); @@ -984,7 +1004,7 @@ ecore_eth_rx_queue_start(struct ecore_hwfn *p_hwfn, enum _ecore_status_t rc; /* Allocate a CID for the queue */ - p_cid = ecore_eth_queue_to_cid_pf(p_hwfn, opaque_fid, p_params); + p_cid = ecore_eth_queue_to_cid_pf(p_hwfn, opaque_fid, true, p_params); if (p_cid == OSAL_NULL) return ECORE_NOMEM; @@ -1174,11 +1194,20 @@ ecore_eth_pf_tx_queue_start(struct ecore_hwfn *p_hwfn, void OSAL_IOMEM * *pp_doorbell) { enum _ecore_status_t rc; + u16 pq_id; - /* TODO - set tc in the pq_params for multi-cos */ - rc = ecore_eth_txq_start_ramrod(p_hwfn, p_cid, - pbl_addr, pbl_size, - ecore_get_cm_pq_idx_mcos(p_hwfn, tc)); + /* TODO - set tc in the pq_params for multi-cos. + * If pacing is enabled then select queue according to + * rate limiter availability otherwise select queue based + * on multi cos. + */ + if (IS_ECORE_PACING(p_hwfn)) + pq_id = ecore_get_cm_pq_idx_rl(p_hwfn, p_cid->rel.queue_id); + else + pq_id = ecore_get_cm_pq_idx_mcos(p_hwfn, tc); + + rc = ecore_eth_txq_start_ramrod(p_hwfn, p_cid, pbl_addr, + pbl_size, pq_id); if (rc != ECORE_SUCCESS) return rc; @@ -1200,7 +1229,7 @@ ecore_eth_tx_queue_start(struct ecore_hwfn *p_hwfn, u16 opaque_fid, struct ecore_queue_cid *p_cid; enum _ecore_status_t rc; - p_cid = ecore_eth_queue_to_cid_pf(p_hwfn, opaque_fid, p_params); + p_cid = ecore_eth_queue_to_cid_pf(p_hwfn, opaque_fid, false, p_params); if (p_cid == OSAL_NULL) return ECORE_INVAL; @@ -1545,8 +1574,8 @@ ecore_sp_eth_filter_mcast(struct ecore_hwfn *p_hwfn, enum spq_mode comp_mode, struct ecore_spq_comp_cb *p_comp_data) { - unsigned long bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct vport_update_ramrod_data *p_ramrod = OSAL_NULL; + u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct ecore_spq_entry *p_ent = OSAL_NULL; struct ecore_sp_init_data init_data; u8 abs_vport_id = 0; @@ -1585,8 +1614,7 @@ ecore_sp_eth_filter_mcast(struct ecore_hwfn *p_hwfn, /* explicitly clear out the entire vector */ OSAL_MEMSET(&p_ramrod->approx_mcast.bins, 0, sizeof(p_ramrod->approx_mcast.bins)); - OSAL_MEMSET(bins, 0, sizeof(unsigned long) * - ETH_MULTICAST_MAC_BINS_IN_REGS); + OSAL_MEMSET(bins, 0, sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS); /* filter ADD op is explicit set op and it removes * any existing filters for the vport. */ @@ -1595,16 +1623,15 @@ ecore_sp_eth_filter_mcast(struct ecore_hwfn *p_hwfn, u32 bit; bit = ecore_mcast_bin_from_mac(p_filter_cmd->mac[i]); - OSAL_SET_BIT(bit, bins); + bins[bit / 32] |= 1 << (bit % 32); } /* Convert to correct endianity */ for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { struct vport_update_ramrod_mcast *p_ramrod_bins; - u32 *p_bins = (u32 *)bins; p_ramrod_bins = &p_ramrod->approx_mcast; - p_ramrod_bins->bins[i] = OSAL_CPU_TO_LE32(p_bins[i]); + p_ramrod_bins->bins[i] = OSAL_CPU_TO_LE32(bins[i]); } } @@ -1934,6 +1961,11 @@ static void __ecore_get_vport_port_stats(struct ecore_hwfn *p_hwfn, p_ah->tx_1519_to_max_byte_packets = port_stats.eth.u1.ah1.t1519_to_max; } + + p_common->link_change_count = ecore_rd(p_hwfn, p_ptt, + p_hwfn->mcp_info->port_addr + + OFFSETOF(struct public_port, + link_change_count)); } void __ecore_get_vport_stats(struct ecore_hwfn *p_hwfn, @@ -1968,6 +2000,7 @@ static void _ecore_get_vport_stats(struct ecore_dev *p_dev, struct ecore_hwfn *p_hwfn = &p_dev->hwfns[i]; struct ecore_ptt *p_ptt = IS_PF(p_dev) ? ecore_ptt_acquire(p_hwfn) : OSAL_NULL; + bool b_get_port_stats; if (IS_PF(p_dev)) { /* The main vport index is relative first */ @@ -1982,8 +2015,9 @@ static void _ecore_get_vport_stats(struct ecore_dev *p_dev, continue; } + b_get_port_stats = IS_PF(p_dev) && IS_LEAD_HWFN(p_hwfn); __ecore_get_vport_stats(p_hwfn, p_ptt, stats, fw_vport, - IS_PF(p_dev) ? true : false); + b_get_port_stats); out: if (IS_PF(p_dev) && p_ptt) @@ -2048,23 +2082,48 @@ void ecore_reset_vport_stats(struct ecore_dev *p_dev) /* PORT statistics are not necessarily reset, so we need to * read and create a baseline for future statistics. + * Link change stat is maintained by MFW, return its value as is. */ if (!p_dev->reset_stats) DP_INFO(p_dev, "Reset stats not allocated\n"); - else + else { _ecore_get_vport_stats(p_dev, p_dev->reset_stats); + p_dev->reset_stats->common.link_change_count = 0; + } +} + +static enum gft_profile_type +ecore_arfs_mode_to_hsi(enum ecore_filter_config_mode mode) +{ + if (mode == ECORE_FILTER_CONFIG_MODE_5_TUPLE) + return GFT_PROFILE_TYPE_4_TUPLE; + + if (mode == ECORE_FILTER_CONFIG_MODE_IP_DEST) + return GFT_PROFILE_TYPE_IP_DST_ADDR; + + if (mode == ECORE_FILTER_CONFIG_MODE_TUNN_TYPE) + return GFT_PROFILE_TYPE_TUNNEL_TYPE; + + if (mode == ECORE_FILTER_CONFIG_MODE_IP_SRC) + return GFT_PROFILE_TYPE_IP_SRC_ADDR; + + return GFT_PROFILE_TYPE_L4_DST_PORT; } void ecore_arfs_mode_configure(struct ecore_hwfn *p_hwfn, struct ecore_ptt *p_ptt, struct ecore_arfs_config_params *p_cfg_params) { - if (p_cfg_params->arfs_enable) { - ecore_set_rfs_mode_enable(p_hwfn, p_ptt, p_hwfn->rel_pf_id, - p_cfg_params->tcp, - p_cfg_params->udp, - p_cfg_params->ipv4, - p_cfg_params->ipv6); + if (OSAL_TEST_BIT(ECORE_MF_DISABLE_ARFS, &p_hwfn->p_dev->mf_bits)) + return; + + if (p_cfg_params->mode != ECORE_FILTER_CONFIG_MODE_DISABLE) { + ecore_gft_config(p_hwfn, p_ptt, p_hwfn->rel_pf_id, + p_cfg_params->tcp, + p_cfg_params->udp, + p_cfg_params->ipv4, + p_cfg_params->ipv6, + ecore_arfs_mode_to_hsi(p_cfg_params->mode)); DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "tcp = %s, udp = %s, ipv4 = %s, ipv6 =%s\n", p_cfg_params->tcp ? "Enable" : "Disable", @@ -2072,10 +2131,10 @@ void ecore_arfs_mode_configure(struct ecore_hwfn *p_hwfn, p_cfg_params->ipv4 ? "Enable" : "Disable", p_cfg_params->ipv6 ? "Enable" : "Disable"); } else { - ecore_set_rfs_mode_disable(p_hwfn, p_ptt, p_hwfn->rel_pf_id); + ecore_gft_disable(p_hwfn, p_ptt, p_hwfn->rel_pf_id); } - DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Configured ARFS mode : %s\n", - p_cfg_params->arfs_enable ? "Enable" : "Disable"); + DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "Configured ARFS mode : %d\n", + (int)p_cfg_params->mode); } enum _ecore_status_t @@ -2123,9 +2182,17 @@ ecore_configure_rfs_ntuple_filter(struct ecore_hwfn *p_hwfn, DMA_REGPAIR_LE(p_ramrod->pkt_hdr_addr, p_addr); p_ramrod->pkt_hdr_length = OSAL_CPU_TO_LE16(length); - p_ramrod->rx_qid_or_action_icid = OSAL_CPU_TO_LE16(abs_rx_q_id); - p_ramrod->vport_id = abs_vport_id; - p_ramrod->filter_type = RFS_FILTER_TYPE; + + p_ramrod->action_icid_valid = 0; + p_ramrod->action_icid = 0; + + p_ramrod->rx_qid_valid = 1; + p_ramrod->rx_qid = OSAL_CPU_TO_LE16(abs_rx_q_id); + + p_ramrod->flow_id_valid = 0; + p_ramrod->flow_id = 0; + + p_ramrod->vport_id = OSAL_CPU_TO_LE16((u16)abs_vport_id); p_ramrod->filter_action = b_is_add ? GFT_ADD_FILTER : GFT_DELETE_FILTER; @@ -2137,3 +2204,181 @@ ecore_configure_rfs_ntuple_filter(struct ecore_hwfn *p_hwfn, return ecore_spq_post(p_hwfn, p_ent, OSAL_NULL); } + +enum _ecore_status_t ecore_get_rxq_coalesce(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + struct ecore_queue_cid *p_cid, + u16 *p_rx_coal) +{ + u32 coalesce, address, is_valid; + struct cau_sb_entry sb_entry; + u8 timer_res; + enum _ecore_status_t rc; + + rc = ecore_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY + + p_cid->sb_igu_id * sizeof(u64), + (u64)(osal_uintptr_t)&sb_entry, 2, + OSAL_NULL /* default parameters */); + if (rc != ECORE_SUCCESS) { + DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc); + return rc; + } + + timer_res = GET_FIELD(sb_entry.params, CAU_SB_ENTRY_TIMER_RES0); + + address = BAR0_MAP_REG_USDM_RAM + + USTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id); + coalesce = ecore_rd(p_hwfn, p_ptt, address); + + is_valid = GET_FIELD(coalesce, COALESCING_TIMESET_VALID); + if (!is_valid) + return ECORE_INVAL; + + coalesce = GET_FIELD(coalesce, COALESCING_TIMESET_TIMESET); + *p_rx_coal = (u16)(coalesce << timer_res); + + return ECORE_SUCCESS; +} + +enum _ecore_status_t ecore_get_txq_coalesce(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + struct ecore_queue_cid *p_cid, + u16 *p_tx_coal) +{ + u32 coalesce, address, is_valid; + struct cau_sb_entry sb_entry; + u8 timer_res; + enum _ecore_status_t rc; + + rc = ecore_dmae_grc2host(p_hwfn, p_ptt, CAU_REG_SB_VAR_MEMORY + + p_cid->sb_igu_id * sizeof(u64), + (u64)(osal_uintptr_t)&sb_entry, 2, + OSAL_NULL /* default parameters */); + if (rc != ECORE_SUCCESS) { + DP_ERR(p_hwfn, "dmae_grc2host failed %d\n", rc); + return rc; + } + + timer_res = GET_FIELD(sb_entry.params, CAU_SB_ENTRY_TIMER_RES1); + + address = BAR0_MAP_REG_XSDM_RAM + + XSTORM_ETH_QUEUE_ZONE_OFFSET(p_cid->abs.queue_id); + coalesce = ecore_rd(p_hwfn, p_ptt, address); + + is_valid = GET_FIELD(coalesce, COALESCING_TIMESET_VALID); + if (!is_valid) + return ECORE_INVAL; + + coalesce = GET_FIELD(coalesce, COALESCING_TIMESET_TIMESET); + *p_tx_coal = (u16)(coalesce << timer_res); + + return ECORE_SUCCESS; +} + +enum _ecore_status_t +ecore_get_queue_coalesce(struct ecore_hwfn *p_hwfn, u16 *p_coal, + void *handle) +{ + struct ecore_queue_cid *p_cid = (struct ecore_queue_cid *)handle; + enum _ecore_status_t rc = ECORE_SUCCESS; + struct ecore_ptt *p_ptt; + + if (IS_VF(p_hwfn->p_dev)) { + rc = ecore_vf_pf_get_coalesce(p_hwfn, p_coal, p_cid); + if (rc != ECORE_SUCCESS) + DP_NOTICE(p_hwfn, false, + "Unable to read queue calescing\n"); + + return rc; + } + + p_ptt = ecore_ptt_acquire(p_hwfn); + if (!p_ptt) + return ECORE_AGAIN; + + if (p_cid->b_is_rx) { + rc = ecore_get_rxq_coalesce(p_hwfn, p_ptt, p_cid, p_coal); + if (rc != ECORE_SUCCESS) + goto out; + } else { + rc = ecore_get_txq_coalesce(p_hwfn, p_ptt, p_cid, p_coal); + if (rc != ECORE_SUCCESS) + goto out; + } + +out: + ecore_ptt_release(p_hwfn, p_ptt); + + return rc; +} + +enum _ecore_status_t +ecore_eth_tx_queue_maxrate(struct ecore_hwfn *p_hwfn, + struct ecore_ptt *p_ptt, + struct ecore_queue_cid *p_cid, u32 rate) +{ + struct ecore_mcp_link_state *p_link; + u8 vport; + + vport = (u8)ecore_get_qm_vport_idx_rl(p_hwfn, p_cid->rel.queue_id); + p_link = &ECORE_LEADING_HWFN(p_hwfn->p_dev)->mcp_info->link_output; + + DP_VERBOSE(p_hwfn, ECORE_MSG_LINK, + "About to rate limit qm vport %d for queue %d with rate %d\n", + vport, p_cid->rel.queue_id, rate); + + return ecore_init_vport_rl(p_hwfn, p_ptt, vport, rate, + p_link->speed); +} + +#define RSS_TSTORM_UPDATE_STATUS_MAX_POLL_COUNT 100 +#define RSS_TSTORM_UPDATE_STATUS_POLL_PERIOD_US 1 + +enum _ecore_status_t +ecore_update_eth_rss_ind_table_entry(struct ecore_hwfn *p_hwfn, + u8 vport_id, + u8 ind_table_index, + u16 ind_table_value) +{ + struct eth_tstorm_rss_update_data update_data = { 0 }; + void OSAL_IOMEM *addr = OSAL_NULL; + enum _ecore_status_t rc; + u8 abs_vport_id; + u32 cnt = 0; + + OSAL_BUILD_BUG_ON(sizeof(update_data) != sizeof(u64)); + + rc = ecore_fw_vport(p_hwfn, vport_id, &abs_vport_id); + if (rc != ECORE_SUCCESS) + return rc; + + addr = (u8 OSAL_IOMEM *)p_hwfn->regview + + GTT_BAR0_MAP_REG_TSDM_RAM + + TSTORM_ETH_RSS_UPDATE_OFFSET(p_hwfn->rel_pf_id); + + *(u64 *)(&update_data) = DIRECT_REG_RD64(p_hwfn, addr); + + for (cnt = 0; update_data.valid && + cnt < RSS_TSTORM_UPDATE_STATUS_MAX_POLL_COUNT; cnt++) { + OSAL_UDELAY(RSS_TSTORM_UPDATE_STATUS_POLL_PERIOD_US); + *(u64 *)(&update_data) = DIRECT_REG_RD64(p_hwfn, addr); + } + + if (update_data.valid) { + DP_NOTICE(p_hwfn, true, + "rss update valid status is not clear! valid=0x%x vport id=%d ind_Table_idx=%d ind_table_value=%d.\n", + update_data.valid, vport_id, ind_table_index, + ind_table_value); + + return ECORE_AGAIN; + } + + update_data.valid = 1; + update_data.ind_table_index = ind_table_index; + update_data.ind_table_value = ind_table_value; + update_data.vport_id = abs_vport_id; + + DIRECT_REG_WR64(p_hwfn, addr, *(u64 *)(&update_data)); + + return ECORE_SUCCESS; +}