From d635711daa98be86d4c7fd01499c34f566b54ccb Mon Sep 17 00:00:00 2001 From: AndrĂ© Fabian Silva Delgado Date: Fri, 10 Jun 2016 05:30:17 -0300 Subject: Linux-libre 4.6.2-gnu --- drivers/net/ethernet/qlogic/qed/qed_l2.c | 586 +++++++++++++++++++++++++------ 1 file changed, 472 insertions(+), 114 deletions(-) (limited to 'drivers/net/ethernet/qlogic/qed/qed_l2.c') diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index f72036a2e..3f35c6ca9 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -31,6 +31,7 @@ #include "qed_hsi.h" #include "qed_hw.h" #include "qed_int.h" +#include "qed_mcp.h" #include "qed_reg_addr.h" #include "qed_sp.h" @@ -124,52 +125,65 @@ struct qed_sp_vport_update_params { u8 update_vport_active_tx_flg; u8 vport_active_tx_flg; u8 update_approx_mcast_flg; + u8 update_accept_any_vlan_flg; + u8 accept_any_vlan; unsigned long bins[8]; struct qed_rss_params *rss_params; struct qed_filter_accept_flags accept_flags; }; +enum qed_tpa_mode { + QED_TPA_MODE_NONE, + QED_TPA_MODE_UNUSED, + QED_TPA_MODE_GRO, + QED_TPA_MODE_MAX +}; + +struct qed_sp_vport_start_params { + enum qed_tpa_mode tpa_mode; + bool remove_inner_vlan; + bool drop_ttl0; + u8 max_buffers_per_cqe; + u32 concrete_fid; + u16 opaque_fid; + u8 vport_id; + u16 mtu; +}; + #define QED_MAX_SGES_NUM 16 #define CRC32_POLY 0x1edc6f41 static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, - u32 concrete_fid, - u16 opaque_fid, - u8 vport_id, - u16 mtu, - u8 drop_ttl0_flg, - u8 inner_vlan_removal_en_flg) + struct qed_sp_vport_start_params *p_params) { - struct qed_sp_init_request_params params; struct vport_start_ramrod_data *p_ramrod = NULL; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; int rc = -EINVAL; u16 rx_mode = 0; u8 abs_vport_id = 0; - rc = qed_fw_vport(p_hwfn, vport_id, &abs_vport_id); + rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id); if (rc != 0) return rc; - memset(¶ms, 0, sizeof(params)); - params.ramrod_data_size = sizeof(*p_ramrod); - params.comp_mode = QED_SPQ_MODE_EBLOCK; + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = p_params->opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; rc = qed_sp_init_request(p_hwfn, &p_ent, - qed_spq_get_cid(p_hwfn), - opaque_fid, ETH_RAMROD_VPORT_START, - PROTOCOLID_ETH, - ¶ms); + PROTOCOLID_ETH, &init_data); if (rc) return rc; p_ramrod = &p_ent->ramrod.vport_start; p_ramrod->vport_id = abs_vport_id; - p_ramrod->mtu = cpu_to_le16(mtu); - p_ramrod->inner_vlan_removal_en = inner_vlan_removal_en_flg; - p_ramrod->drop_ttl0_en = drop_ttl0_flg; + p_ramrod->mtu = cpu_to_le16(p_params->mtu); + p_ramrod->inner_vlan_removal_en = p_params->remove_inner_vlan; + p_ramrod->drop_ttl0_en = p_params->drop_ttl0; SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_UCAST_DROP_ALL, 1); SET_FIELD(rx_mode, ETH_VPORT_RX_MODE_MCAST_DROP_ALL, 1); @@ -180,9 +194,26 @@ static int qed_sp_vport_start(struct qed_hwfn *p_hwfn, 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; + + switch (p_params->tpa_mode) { + case QED_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_pkt_split_flg = 1; + p_ramrod->tpa_param.tpa_gro_consistent_flg = 1; + break; + default: + break; + } + /* Software Function ID in hwfn (PFs are 0 - 15, VFs are 16 - 135) */ p_ramrod->sw_fid = qed_concrete_to_sw_fid(p_hwfn->cdev, - concrete_fid); + p_params->concrete_fid); return qed_spq_post(p_hwfn, p_ent, NULL); } @@ -360,7 +391,7 @@ qed_sp_vport_update(struct qed_hwfn *p_hwfn, { struct qed_rss_params *p_rss_params = p_params->rss_params; struct vport_update_ramrod_data_cmn *p_cmn; - struct qed_sp_init_request_params sp_params; + struct qed_sp_init_data init_data; struct vport_update_ramrod_data *p_ramrod = NULL; struct qed_spq_entry *p_ent = NULL; u8 abs_vport_id = 0; @@ -370,17 +401,15 @@ qed_sp_vport_update(struct qed_hwfn *p_hwfn, if (rc != 0) return rc; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(*p_ramrod); - sp_params.comp_mode = comp_mode; - sp_params.p_comp_data = p_comp_data; + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = p_params->opaque_fid; + init_data.comp_mode = comp_mode; + init_data.p_comp_data = p_comp_data; rc = qed_sp_init_request(p_hwfn, &p_ent, - qed_spq_get_cid(p_hwfn), - p_params->opaque_fid, ETH_RAMROD_VPORT_UPDATE, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -393,7 +422,9 @@ qed_sp_vport_update(struct qed_hwfn *p_hwfn, p_cmn->update_rx_active_flg = p_params->update_vport_active_rx_flg; p_cmn->tx_active_flg = p_params->vport_active_tx_flg; p_cmn->update_tx_active_flg = p_params->update_vport_active_tx_flg; - + p_cmn->accept_any_vlan = p_params->accept_any_vlan; + p_cmn->update_accept_any_vlan_flg = + p_params->update_accept_any_vlan_flg; rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params); if (rc) { /* Return spq entry which is taken in qed_sp_init_request()*/ @@ -412,8 +443,8 @@ static int qed_sp_vport_stop(struct qed_hwfn *p_hwfn, u16 opaque_fid, u8 vport_id) { - struct qed_sp_init_request_params sp_params; struct vport_stop_ramrod_data *p_ramrod; + struct qed_sp_init_data init_data; struct qed_spq_entry *p_ent; u8 abs_vport_id = 0; int rc; @@ -422,16 +453,14 @@ static int qed_sp_vport_stop(struct qed_hwfn *p_hwfn, if (rc != 0) return rc; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(*p_ramrod); - sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; rc = qed_sp_init_request(p_hwfn, &p_ent, - qed_spq_get_cid(p_hwfn), - opaque_fid, ETH_RAMROD_VPORT_STOP, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -444,8 +473,10 @@ static int qed_sp_vport_stop(struct qed_hwfn *p_hwfn, static int qed_filter_accept_cmd(struct qed_dev *cdev, u8 vport, struct qed_filter_accept_flags accept_flags, - enum spq_mode comp_mode, - struct qed_spq_comp_cb *p_comp_data) + u8 update_accept_any_vlan, + u8 accept_any_vlan, + enum spq_mode comp_mode, + struct qed_spq_comp_cb *p_comp_data) { struct qed_sp_vport_update_params vport_update_params; int i, rc; @@ -454,6 +485,8 @@ static int qed_filter_accept_cmd(struct qed_dev *cdev, memset(&vport_update_params, 0, sizeof(vport_update_params)); vport_update_params.vport_id = vport; vport_update_params.accept_flags = accept_flags; + vport_update_params.update_accept_any_vlan_flg = update_accept_any_vlan; + vport_update_params.accept_any_vlan = accept_any_vlan; for_each_hwfn(cdev, i) { struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; @@ -471,6 +504,10 @@ static int qed_filter_accept_cmd(struct qed_dev *cdev, "Accept filter configured, flags = [Rx]%x [Tx]%x\n", accept_flags.rx_accept_filter, accept_flags.tx_accept_filter); + if (update_accept_any_vlan) + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "accept_any_vlan=%d configured\n", + accept_any_vlan); } return 0; @@ -502,8 +539,8 @@ qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn, u16 cqe_pbl_size) { struct rx_queue_start_ramrod_data *p_ramrod = NULL; - struct qed_sp_init_request_params sp_params; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; struct qed_hw_cid_data *p_rx_cid; u16 abs_rx_q_id = 0; u8 abs_vport_id = 0; @@ -528,15 +565,15 @@ qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn, opaque_fid, cid, params->queue_id, params->vport_id, params->sb); - memset(&sp_params, 0, sizeof(params)); - sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; - sp_params.ramrod_data_size = sizeof(*p_ramrod); + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = cid; + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; rc = qed_sp_init_request(p_hwfn, &p_ent, - cid, opaque_fid, ETH_RAMROD_RX_QUEUE_START, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -551,12 +588,10 @@ qed_sp_eth_rxq_start_ramrod(struct qed_hwfn *p_hwfn, p_ramrod->complete_event_flg = 1; p_ramrod->bd_max_bytes = cpu_to_le16(bd_max_bytes); - p_ramrod->bd_base.hi = DMA_HI_LE(bd_chain_phys_addr); - p_ramrod->bd_base.lo = DMA_LO_LE(bd_chain_phys_addr); + DMA_REGPAIR_LE(p_ramrod->bd_base, bd_chain_phys_addr); p_ramrod->num_of_pbl_pages = cpu_to_le16(cqe_pbl_size); - p_ramrod->cqe_pbl_addr.hi = DMA_HI_LE(cqe_pbl_addr); - p_ramrod->cqe_pbl_addr.lo = DMA_LO_LE(cqe_pbl_addr); + DMA_REGPAIR_LE(p_ramrod->cqe_pbl_addr, cqe_pbl_addr); rc = qed_spq_post(p_hwfn, p_ent, NULL); @@ -628,21 +663,20 @@ static int qed_sp_eth_rx_queue_stop(struct qed_hwfn *p_hwfn, { struct qed_hw_cid_data *p_rx_cid = &p_hwfn->p_rx_cids[rx_queue_id]; struct rx_queue_stop_ramrod_data *p_ramrod = NULL; - struct qed_sp_init_request_params sp_params; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; u16 abs_rx_q_id = 0; int rc = -EINVAL; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(*p_ramrod); - sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = p_rx_cid->cid; + init_data.opaque_fid = p_rx_cid->opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; rc = qed_sp_init_request(p_hwfn, &p_ent, - p_rx_cid->cid, - p_rx_cid->opaque_fid, ETH_RAMROD_RX_QUEUE_STOP, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -680,8 +714,8 @@ qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn, union qed_qm_pq_params *p_pq_params) { struct tx_queue_start_ramrod_data *p_ramrod = NULL; - struct qed_sp_init_request_params sp_params; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; struct qed_hw_cid_data *p_tx_cid; u8 abs_vport_id; int rc = -EINVAL; @@ -696,15 +730,15 @@ qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn, if (rc) return rc; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(*p_ramrod); - sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = cid; + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; - rc = qed_sp_init_request(p_hwfn, &p_ent, cid, - opaque_fid, + rc = qed_sp_init_request(p_hwfn, &p_ent, ETH_RAMROD_TX_QUEUE_START, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -714,11 +748,9 @@ qed_sp_eth_txq_start_ramrod(struct qed_hwfn *p_hwfn, p_ramrod->sb_id = cpu_to_le16(p_params->sb); p_ramrod->sb_index = p_params->sb_idx; p_ramrod->stats_counter_id = stats_id; - p_ramrod->tc = p_pq_params->eth.tc; p_ramrod->pbl_size = cpu_to_le16(pbl_size); - p_ramrod->pbl_base_addr.hi = DMA_HI_LE(pbl_addr); - p_ramrod->pbl_base_addr.lo = DMA_LO_LE(pbl_addr); + DMA_REGPAIR_LE(p_ramrod->pbl_base_addr, pbl_addr); pq_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ETH, @@ -785,20 +817,19 @@ static int qed_sp_eth_tx_queue_stop(struct qed_hwfn *p_hwfn, u16 tx_queue_id) { struct qed_hw_cid_data *p_tx_cid = &p_hwfn->p_tx_cids[tx_queue_id]; - struct qed_sp_init_request_params sp_params; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; int rc = -EINVAL; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(struct tx_queue_stop_ramrod_data); - sp_params.comp_mode = QED_SPQ_MODE_EBLOCK; + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = p_tx_cid->cid; + init_data.opaque_fid = p_tx_cid->opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; rc = qed_sp_init_request(p_hwfn, &p_ent, - p_tx_cid->cid, - p_tx_cid->opaque_fid, ETH_RAMROD_TX_QUEUE_STOP, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -821,9 +852,8 @@ qed_filter_action(enum qed_filter_opcode opcode) case QED_FILTER_REMOVE: action = ETH_FILTER_ACTION_REMOVE; break; - case QED_FILTER_REPLACE: case QED_FILTER_FLUSH: - action = ETH_FILTER_ACTION_REPLACE; + action = ETH_FILTER_ACTION_REMOVE_ALL; break; default: action = MAX_ETH_FILTER_ACTION; @@ -856,9 +886,9 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn, { u8 vport_to_add_to = 0, vport_to_remove_from = 0; struct vport_filter_update_ramrod_data *p_ramrod; - struct qed_sp_init_request_params sp_params; struct eth_filter_cmd *p_first_filter; struct eth_filter_cmd *p_second_filter; + struct qed_sp_init_data init_data; enum eth_filter_action action; int rc; @@ -872,17 +902,16 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn, if (rc) return rc; - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(**pp_ramrod); - sp_params.comp_mode = comp_mode; - sp_params.p_comp_data = p_comp_data; + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = comp_mode; + init_data.p_comp_data = p_comp_data; rc = qed_sp_init_request(p_hwfn, pp_ent, - qed_spq_get_cid(p_hwfn), - opaque_fid, ETH_RAMROD_FILTERS_UPDATE, - PROTOCOLID_ETH, - &sp_params); + PROTOCOLID_ETH, &init_data); if (rc) return rc; @@ -892,8 +921,7 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn, p_ramrod->filter_cmd_hdr.tx = p_filter_cmd->is_tx_filter ? 1 : 0; switch (p_filter_cmd->opcode) { - case QED_FILTER_FLUSH: - p_ramrod->filter_cmd_hdr.cmd_cnt = 0; break; + case QED_FILTER_REPLACE: case QED_FILTER_MOVE: p_ramrod->filter_cmd_hdr.cmd_cnt = 2; break; default: @@ -962,6 +990,12 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn, p_second_filter->action = ETH_FILTER_ACTION_ADD; p_second_filter->vport_id = vport_to_add_to; + } else if (p_filter_cmd->opcode == QED_FILTER_REPLACE) { + p_first_filter->vport_id = vport_to_add_to; + memcpy(p_second_filter, p_first_filter, + sizeof(*p_second_filter)); + p_first_filter->action = ETH_FILTER_ACTION_REMOVE_ALL; + p_second_filter->action = ETH_FILTER_ACTION_ADD; } else { action = qed_filter_action(p_filter_cmd->opcode); @@ -1101,8 +1135,8 @@ qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, { unsigned long bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct vport_update_ramrod_data *p_ramrod = NULL; - struct qed_sp_init_request_params sp_params; struct qed_spq_entry *p_ent = NULL; + struct qed_sp_init_data init_data; u8 abs_vport_id = 0; int rc, i; @@ -1118,18 +1152,16 @@ qed_sp_eth_filter_mcast(struct qed_hwfn *p_hwfn, return rc; } - memset(&sp_params, 0, sizeof(sp_params)); - sp_params.ramrod_data_size = sizeof(*p_ramrod); - sp_params.comp_mode = comp_mode; - sp_params.p_comp_data = p_comp_data; + /* Get SPQ entry */ + memset(&init_data, 0, sizeof(init_data)); + init_data.cid = qed_spq_get_cid(p_hwfn); + init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; + init_data.comp_mode = comp_mode; + init_data.p_comp_data = p_comp_data; rc = qed_sp_init_request(p_hwfn, &p_ent, - qed_spq_get_cid(p_hwfn), - p_hwfn->hw_info.opaque_fid, ETH_RAMROD_VPORT_UPDATE, - PROTOCOLID_ETH, - &sp_params); - + PROTOCOLID_ETH, &init_data); if (rc) { DP_ERR(p_hwfn, "Multi-cast command failed %d\n", rc); return rc; @@ -1230,6 +1262,328 @@ static int qed_filter_ucast_cmd(struct qed_dev *cdev, return rc; } +/* Statistics related code */ +static void __qed_get_vport_pstats_addrlen(struct qed_hwfn *p_hwfn, + u32 *p_addr, + u32 *p_len, + u16 statistics_bin) +{ + *p_addr = BAR0_MAP_REG_PSDM_RAM + + PSTORM_QUEUE_STAT_OFFSET(statistics_bin); + *p_len = sizeof(struct eth_pstorm_per_queue_stat); +} + +static void __qed_get_vport_pstats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, + u16 statistics_bin) +{ + struct eth_pstorm_per_queue_stat pstats; + u32 pstats_addr = 0, pstats_len = 0; + + __qed_get_vport_pstats_addrlen(p_hwfn, &pstats_addr, &pstats_len, + statistics_bin); + + memset(&pstats, 0, sizeof(pstats)); + qed_memcpy_from(p_hwfn, p_ptt, &pstats, + pstats_addr, pstats_len); + + p_stats->tx_ucast_bytes += + HILO_64_REGPAIR(pstats.sent_ucast_bytes); + p_stats->tx_mcast_bytes += + HILO_64_REGPAIR(pstats.sent_mcast_bytes); + p_stats->tx_bcast_bytes += + HILO_64_REGPAIR(pstats.sent_bcast_bytes); + p_stats->tx_ucast_pkts += + HILO_64_REGPAIR(pstats.sent_ucast_pkts); + p_stats->tx_mcast_pkts += + HILO_64_REGPAIR(pstats.sent_mcast_pkts); + p_stats->tx_bcast_pkts += + HILO_64_REGPAIR(pstats.sent_bcast_pkts); + p_stats->tx_err_drop_pkts += + HILO_64_REGPAIR(pstats.error_drop_pkts); +} + +static void __qed_get_vport_tstats_addrlen(struct qed_hwfn *p_hwfn, + u32 *p_addr, + u32 *p_len) +{ + *p_addr = BAR0_MAP_REG_TSDM_RAM + + TSTORM_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)); + *p_len = sizeof(struct tstorm_per_port_stat); +} + +static void __qed_get_vport_tstats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, + u16 statistics_bin) +{ + u32 tstats_addr = 0, tstats_len = 0; + struct tstorm_per_port_stat tstats; + + __qed_get_vport_tstats_addrlen(p_hwfn, &tstats_addr, &tstats_len); + + memset(&tstats, 0, sizeof(tstats)); + qed_memcpy_from(p_hwfn, p_ptt, &tstats, + tstats_addr, tstats_len); + + p_stats->mftag_filter_discards += + HILO_64_REGPAIR(tstats.mftag_filter_discard); + p_stats->mac_filter_discards += + HILO_64_REGPAIR(tstats.eth_mac_filter_discard); +} + +static void __qed_get_vport_ustats_addrlen(struct qed_hwfn *p_hwfn, + u32 *p_addr, + u32 *p_len, + u16 statistics_bin) +{ + *p_addr = BAR0_MAP_REG_USDM_RAM + + USTORM_QUEUE_STAT_OFFSET(statistics_bin); + *p_len = sizeof(struct eth_ustorm_per_queue_stat); +} + +static void __qed_get_vport_ustats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, + u16 statistics_bin) +{ + struct eth_ustorm_per_queue_stat ustats; + u32 ustats_addr = 0, ustats_len = 0; + + __qed_get_vport_ustats_addrlen(p_hwfn, &ustats_addr, &ustats_len, + statistics_bin); + + memset(&ustats, 0, sizeof(ustats)); + qed_memcpy_from(p_hwfn, p_ptt, &ustats, + ustats_addr, ustats_len); + + p_stats->rx_ucast_bytes += + HILO_64_REGPAIR(ustats.rcv_ucast_bytes); + p_stats->rx_mcast_bytes += + HILO_64_REGPAIR(ustats.rcv_mcast_bytes); + p_stats->rx_bcast_bytes += + HILO_64_REGPAIR(ustats.rcv_bcast_bytes); + p_stats->rx_ucast_pkts += + HILO_64_REGPAIR(ustats.rcv_ucast_pkts); + p_stats->rx_mcast_pkts += + HILO_64_REGPAIR(ustats.rcv_mcast_pkts); + p_stats->rx_bcast_pkts += + HILO_64_REGPAIR(ustats.rcv_bcast_pkts); +} + +static void __qed_get_vport_mstats_addrlen(struct qed_hwfn *p_hwfn, + u32 *p_addr, + u32 *p_len, + u16 statistics_bin) +{ + *p_addr = BAR0_MAP_REG_MSDM_RAM + + MSTORM_QUEUE_STAT_OFFSET(statistics_bin); + *p_len = sizeof(struct eth_mstorm_per_queue_stat); +} + +static void __qed_get_vport_mstats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats, + u16 statistics_bin) +{ + struct eth_mstorm_per_queue_stat mstats; + u32 mstats_addr = 0, mstats_len = 0; + + __qed_get_vport_mstats_addrlen(p_hwfn, &mstats_addr, &mstats_len, + statistics_bin); + + memset(&mstats, 0, sizeof(mstats)); + qed_memcpy_from(p_hwfn, p_ptt, &mstats, + mstats_addr, mstats_len); + + p_stats->no_buff_discards += + HILO_64_REGPAIR(mstats.no_buff_discard); + p_stats->packet_too_big_discard += + HILO_64_REGPAIR(mstats.packet_too_big_discard); + p_stats->ttl0_discard += + HILO_64_REGPAIR(mstats.ttl0_discard); + p_stats->tpa_coalesced_pkts += + HILO_64_REGPAIR(mstats.tpa_coalesced_pkts); + p_stats->tpa_coalesced_events += + HILO_64_REGPAIR(mstats.tpa_coalesced_events); + p_stats->tpa_aborts_num += + HILO_64_REGPAIR(mstats.tpa_aborts_num); + p_stats->tpa_coalesced_bytes += + HILO_64_REGPAIR(mstats.tpa_coalesced_bytes); +} + +static void __qed_get_vport_port_stats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *p_stats) +{ + struct port_stats port_stats; + int j; + + memset(&port_stats, 0, sizeof(port_stats)); + + qed_memcpy_from(p_hwfn, p_ptt, &port_stats, + p_hwfn->mcp_info->port_addr + + offsetof(struct public_port, stats), + sizeof(port_stats)); + + p_stats->rx_64_byte_packets += port_stats.pmm.r64; + p_stats->rx_127_byte_packets += port_stats.pmm.r127; + p_stats->rx_255_byte_packets += port_stats.pmm.r255; + p_stats->rx_511_byte_packets += port_stats.pmm.r511; + p_stats->rx_1023_byte_packets += port_stats.pmm.r1023; + p_stats->rx_1518_byte_packets += port_stats.pmm.r1518; + p_stats->rx_1522_byte_packets += port_stats.pmm.r1522; + p_stats->rx_2047_byte_packets += port_stats.pmm.r2047; + p_stats->rx_4095_byte_packets += port_stats.pmm.r4095; + p_stats->rx_9216_byte_packets += port_stats.pmm.r9216; + p_stats->rx_16383_byte_packets += port_stats.pmm.r16383; + p_stats->rx_crc_errors += port_stats.pmm.rfcs; + p_stats->rx_mac_crtl_frames += port_stats.pmm.rxcf; + p_stats->rx_pause_frames += port_stats.pmm.rxpf; + p_stats->rx_pfc_frames += port_stats.pmm.rxpp; + p_stats->rx_align_errors += port_stats.pmm.raln; + p_stats->rx_carrier_errors += port_stats.pmm.rfcr; + p_stats->rx_oversize_packets += port_stats.pmm.rovr; + p_stats->rx_jabbers += port_stats.pmm.rjbr; + p_stats->rx_undersize_packets += port_stats.pmm.rund; + p_stats->rx_fragments += port_stats.pmm.rfrg; + p_stats->tx_64_byte_packets += port_stats.pmm.t64; + p_stats->tx_65_to_127_byte_packets += port_stats.pmm.t127; + p_stats->tx_128_to_255_byte_packets += port_stats.pmm.t255; + p_stats->tx_256_to_511_byte_packets += port_stats.pmm.t511; + p_stats->tx_512_to_1023_byte_packets += port_stats.pmm.t1023; + p_stats->tx_1024_to_1518_byte_packets += port_stats.pmm.t1518; + p_stats->tx_1519_to_2047_byte_packets += port_stats.pmm.t2047; + p_stats->tx_2048_to_4095_byte_packets += port_stats.pmm.t4095; + p_stats->tx_4096_to_9216_byte_packets += port_stats.pmm.t9216; + p_stats->tx_9217_to_16383_byte_packets += port_stats.pmm.t16383; + p_stats->tx_pause_frames += port_stats.pmm.txpf; + p_stats->tx_pfc_frames += port_stats.pmm.txpp; + p_stats->tx_lpi_entry_count += port_stats.pmm.tlpiec; + p_stats->tx_total_collisions += port_stats.pmm.tncl; + p_stats->rx_mac_bytes += port_stats.pmm.rbyte; + p_stats->rx_mac_uc_packets += port_stats.pmm.rxuca; + p_stats->rx_mac_mc_packets += port_stats.pmm.rxmca; + p_stats->rx_mac_bc_packets += port_stats.pmm.rxbca; + p_stats->rx_mac_frames_ok += port_stats.pmm.rxpok; + p_stats->tx_mac_bytes += port_stats.pmm.tbyte; + p_stats->tx_mac_uc_packets += port_stats.pmm.txuca; + p_stats->tx_mac_mc_packets += port_stats.pmm.txmca; + p_stats->tx_mac_bc_packets += port_stats.pmm.txbca; + p_stats->tx_mac_ctrl_frames += port_stats.pmm.txcf; + for (j = 0; j < 8; j++) { + p_stats->brb_truncates += port_stats.brb.brb_truncate[j]; + p_stats->brb_discards += port_stats.brb.brb_discard[j]; + } +} + +static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + struct qed_eth_stats *stats, + u16 statistics_bin) +{ + __qed_get_vport_mstats(p_hwfn, p_ptt, stats, statistics_bin); + __qed_get_vport_ustats(p_hwfn, p_ptt, stats, statistics_bin); + __qed_get_vport_tstats(p_hwfn, p_ptt, stats, statistics_bin); + __qed_get_vport_pstats(p_hwfn, p_ptt, stats, statistics_bin); + + if (p_hwfn->mcp_info) + __qed_get_vport_port_stats(p_hwfn, p_ptt, stats); +} + +static void _qed_get_vport_stats(struct qed_dev *cdev, + struct qed_eth_stats *stats) +{ + u8 fw_vport = 0; + int i; + + memset(stats, 0, sizeof(*stats)); + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct qed_ptt *p_ptt; + + /* The main vport index is relative first */ + if (qed_fw_vport(p_hwfn, 0, &fw_vport)) { + DP_ERR(p_hwfn, "No vport available!\n"); + continue; + } + + p_ptt = qed_ptt_acquire(p_hwfn); + if (!p_ptt) { + DP_ERR(p_hwfn, "Failed to acquire ptt\n"); + continue; + } + + __qed_get_vport_stats(p_hwfn, p_ptt, stats, fw_vport); + + qed_ptt_release(p_hwfn, p_ptt); + } +} + +void qed_get_vport_stats(struct qed_dev *cdev, + struct qed_eth_stats *stats) +{ + u32 i; + + if (!cdev) { + memset(stats, 0, sizeof(*stats)); + return; + } + + _qed_get_vport_stats(cdev, stats); + + if (!cdev->reset_stats) + return; + + /* Reduce the statistics baseline */ + for (i = 0; i < sizeof(struct qed_eth_stats) / sizeof(u64); i++) + ((u64 *)stats)[i] -= ((u64 *)cdev->reset_stats)[i]; +} + +/* zeroes V-PORT specific portion of stats (Port stats remains untouched) */ +void qed_reset_vport_stats(struct qed_dev *cdev) +{ + int i; + + for_each_hwfn(cdev, i) { + struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; + struct eth_mstorm_per_queue_stat mstats; + struct eth_ustorm_per_queue_stat ustats; + struct eth_pstorm_per_queue_stat pstats; + struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn); + u32 addr = 0, len = 0; + + if (!p_ptt) { + DP_ERR(p_hwfn, "Failed to acquire ptt\n"); + continue; + } + + memset(&mstats, 0, sizeof(mstats)); + __qed_get_vport_mstats_addrlen(p_hwfn, &addr, &len, 0); + qed_memcpy_to(p_hwfn, p_ptt, addr, &mstats, len); + + memset(&ustats, 0, sizeof(ustats)); + __qed_get_vport_ustats_addrlen(p_hwfn, &addr, &len, 0); + qed_memcpy_to(p_hwfn, p_ptt, addr, &ustats, len); + + memset(&pstats, 0, sizeof(pstats)); + __qed_get_vport_pstats_addrlen(p_hwfn, &addr, &len, 0); + qed_memcpy_to(p_hwfn, p_ptt, addr, &pstats, len); + + qed_ptt_release(p_hwfn, p_ptt); + } + + /* PORT statistics are not necessarily reset, so we need to + * read and create a baseline for future statistics. + */ + if (!cdev->reset_stats) + DP_INFO(cdev, "Reset stats not allocated\n"); + else + _qed_get_vport_stats(cdev, cdev->reset_stats); +} + static int qed_fill_eth_dev_info(struct qed_dev *cdev, struct qed_dev_eth_info *info) { @@ -1268,24 +1622,25 @@ static void qed_register_eth_ops(struct qed_dev *cdev, } static int qed_start_vport(struct qed_dev *cdev, - u8 vport_id, - u16 mtu, - u8 drop_ttl0_flg, - u8 inner_vlan_removal_en_flg) + struct qed_start_vport_params *params) { int rc, i; for_each_hwfn(cdev, i) { + struct qed_sp_vport_start_params start = { 0 }; struct qed_hwfn *p_hwfn = &cdev->hwfns[i]; - rc = qed_sp_vport_start(p_hwfn, - p_hwfn->hw_info.concrete_fid, - p_hwfn->hw_info.opaque_fid, - vport_id, - mtu, - drop_ttl0_flg, - inner_vlan_removal_en_flg); - + start.tpa_mode = params->gro_enable ? QED_TPA_MODE_GRO : + QED_TPA_MODE_NONE; + start.remove_inner_vlan = params->remove_inner_vlan; + start.drop_ttl0 = params->drop_ttl0; + start.opaque_fid = p_hwfn->hw_info.opaque_fid; + start.concrete_fid = p_hwfn->hw_info.concrete_fid; + start.vport_id = params->vport_id; + start.max_buffers_per_cqe = 16; + start.mtu = params->mtu; + + rc = qed_sp_vport_start(p_hwfn, &start); if (rc) { DP_ERR(cdev, "Failed to start VPORT\n"); return rc; @@ -1295,7 +1650,7 @@ static int qed_start_vport(struct qed_dev *cdev, DP_VERBOSE(cdev, (QED_MSG_SPQ | NETIF_MSG_IFUP), "Started V-PORT %d with MTU %d\n", - vport_id, mtu); + start.vport_id, start.mtu); } qed_reset_vport_stats(cdev); @@ -1344,6 +1699,9 @@ static int qed_update_vport(struct qed_dev *cdev, params->update_vport_active_flg; sp_params.vport_active_rx_flg = params->vport_active_flg; sp_params.vport_active_tx_flg = params->vport_active_flg; + sp_params.accept_any_vlan = params->accept_any_vlan; + sp_params.update_accept_any_vlan_flg = + params->update_accept_any_vlan_flg; /* RSS - is a bit tricky, since upper-layer isn't familiar with hwfns. * We need to re-fix the rss values per engine for CMT. @@ -1563,7 +1921,7 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev, else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED; - return qed_filter_accept_cmd(cdev, 0, accept_flags, + return qed_filter_accept_cmd(cdev, 0, accept_flags, false, false, QED_SPQ_MODE_CB, NULL); } -- cgit v1.2.3-54-g00ecf