X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fsfc%2Fsfc_port.c;h=32a0894a55d96ea5738695683a32a2292dc69e20;hb=27dc00646f54c5fd885ecbd7498d3158ed2fc458;hp=c423f52741db101914090c036f0c3c09fe04989d;hpb=ff6a1197c3b1f8e061dd698e509313f15c3aaf1d;p=dpdk.git diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c index c423f52741..32a0894a55 100644 --- a/drivers/net/sfc/sfc_port.c +++ b/drivers/net/sfc/sfc_port.c @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause * - * Copyright (c) 2016-2018 Solarflare Communications Inc. - * All rights reserved. + * Copyright(c) 2019-2020 Xilinx, Inc. + * Copyright(c) 2016-2019 Solarflare Communications Inc. * * This software was jointly developed between OKTET Labs (under contract * for Solarflare) and Solarflare Communications, Inc. @@ -87,6 +87,18 @@ sfc_port_update_mac_stats(struct sfc_adapter *sa) return 0; } +static void +sfc_port_reset_sw_stats(struct sfc_adapter *sa) +{ + struct sfc_port *port = &sa->port; + + /* + * Reset diff stats explicitly since check which does not allow + * the statistics to grow backward could deny it. + */ + port->ipackets = 0; +} + int sfc_port_reset_mac_stats(struct sfc_adapter *sa) { @@ -95,6 +107,8 @@ sfc_port_reset_mac_stats(struct sfc_adapter *sa) rte_spinlock_lock(&port->mac_stats_lock); rc = efx_mac_stats_clear(sa->nic); + if (rc == 0) + sfc_port_reset_sw_stats(sa); rte_spinlock_unlock(&port->mac_stats_lock); return rc; @@ -121,6 +135,28 @@ sfc_port_init_dev_link(struct sfc_adapter *sa) return 0; } +#if EFSYS_OPT_LOOPBACK + +static efx_link_mode_t +sfc_port_phy_caps_to_max_link_speed(uint32_t phy_caps) +{ + if (phy_caps & (1u << EFX_PHY_CAP_100000FDX)) + return EFX_LINK_100000FDX; + if (phy_caps & (1u << EFX_PHY_CAP_50000FDX)) + return EFX_LINK_50000FDX; + if (phy_caps & (1u << EFX_PHY_CAP_40000FDX)) + return EFX_LINK_40000FDX; + if (phy_caps & (1u << EFX_PHY_CAP_25000FDX)) + return EFX_LINK_25000FDX; + if (phy_caps & (1u << EFX_PHY_CAP_10000FDX)) + return EFX_LINK_10000FDX; + if (phy_caps & (1u << EFX_PHY_CAP_1000FDX)) + return EFX_LINK_1000FDX; + return EFX_LINK_UNKNOWN; +} + +#endif + int sfc_port_start(struct sfc_adapter *sa) { @@ -143,6 +179,21 @@ sfc_port_start(struct sfc_adapter *sa) if (rc != 0) goto fail_port_init; +#if EFSYS_OPT_LOOPBACK + if (sa->eth_dev->data->dev_conf.lpbk_mode != 0) { + efx_link_mode_t link_mode; + + link_mode = + sfc_port_phy_caps_to_max_link_speed(port->phy_adv_cap); + sfc_log_init(sa, "set loopback link_mode=%u type=%u", link_mode, + sa->eth_dev->data->dev_conf.lpbk_mode); + rc = efx_port_loopback_set(sa->nic, link_mode, + sa->eth_dev->data->dev_conf.lpbk_mode); + if (rc != 0) + goto fail_loopback_set; + } +#endif + sfc_log_init(sa, "set flow control to %#x autoneg=%u", port->flow_ctrl, port->flow_ctrl_autoneg); rc = efx_mac_fcntl_set(sa->nic, port->flow_ctrl, @@ -155,6 +206,16 @@ sfc_port_start(struct sfc_adapter *sa) SFC_ASSERT((port->phy_adv_cap & phy_pause_caps) == 0); phy_adv_cap = port->phy_adv_cap | (phy_adv_cap & phy_pause_caps); + /* + * No controls for FEC yet. Use default FEC mode. + * I.e. advertise everything supported (*_FEC=1), but do not request + * anything explicitly (*_FEC_REQUESTED=0). + */ + phy_adv_cap |= port->phy_adv_cap_mask & + (1u << EFX_PHY_CAP_BASER_FEC | + 1u << EFX_PHY_CAP_RS_FEC | + 1u << EFX_PHY_CAP_25G_BASER_FEC); + sfc_log_init(sa, "set phy adv caps to %#x", phy_adv_cap); rc = efx_phy_adv_cap_set(sa->nic, phy_adv_cap); if (rc != 0) @@ -165,8 +226,8 @@ sfc_port_start(struct sfc_adapter *sa) if (rc != 0) goto fail_mac_pdu_set; - if (!port->isolated) { - struct ether_addr *addr = &port->default_mac_addr; + if (!sfc_sa2shared(sa)->isolated) { + struct rte_ether_addr *addr = &port->default_mac_addr; sfc_log_init(sa, "set MAC address"); rc = efx_mac_addr_set(sa->nic, addr->addr_bytes); @@ -178,7 +239,7 @@ sfc_port_start(struct sfc_adapter *sa) B_TRUE : B_FALSE; port->allmulti = (sa->eth_dev->data->all_multicast != 0) ? B_TRUE : B_FALSE; - rc = sfc_set_rx_mode(sa); + rc = sfc_set_rx_mode_unchecked(sa); if (rc != 0) goto fail_mac_filter_set; @@ -268,6 +329,9 @@ fail_mac_addr_set: fail_mac_pdu_set: fail_phy_adv_cap_set: fail_mac_fcntl_set: +#if EFSYS_OPT_LOOPBACK +fail_loopback_set: +#endif efx_port_fini(sa->nic); fail_port_init: @@ -322,7 +386,9 @@ sfc_port_attach(struct sfc_adapter *sa) { struct sfc_port *port = &sa->port; const efx_nic_cfg_t *encp = efx_nic_cfg_get(sa->nic); - const struct ether_addr *from; + const struct rte_ether_addr *from; + uint32_t mac_nstats; + size_t mac_stats_size; long kvarg_stats_update_period_ms; int rc; @@ -335,8 +401,8 @@ sfc_port_attach(struct sfc_adapter *sa) port->flow_ctrl_autoneg = B_TRUE; RTE_BUILD_BUG_ON(sizeof(encp->enc_mac_addr) != sizeof(*from)); - from = (const struct ether_addr *)(encp->enc_mac_addr); - ether_addr_copy(from, &port->default_mac_addr); + from = (const struct rte_ether_addr *)(encp->enc_mac_addr); + rte_ether_addr_copy(from, &port->default_mac_addr); port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX; port->nb_mcast_addrs = 0; @@ -358,7 +424,9 @@ sfc_port_attach(struct sfc_adapter *sa) if (port->mac_stats_buf == NULL) goto fail_mac_stats_buf_alloc; - rc = sfc_dma_alloc(sa, "mac_stats", 0, EFX_MAC_STATS_SIZE, + mac_nstats = efx_nic_cfg_get(sa->nic)->enc_mac_stats_nstats; + mac_stats_size = RTE_ALIGN(mac_nstats * sizeof(uint64_t), EFX_BUF_SIZE); + rc = sfc_dma_alloc(sa, "mac_stats", 0, mac_stats_size, sa->socket_id, &port->mac_stats_dma_mem); if (rc != 0) goto fail_mac_stats_dma_alloc; @@ -417,16 +485,70 @@ sfc_port_detach(struct sfc_adapter *sa) sfc_log_init(sa, "done"); } +static boolean_t +sfc_get_requested_all_ucast(struct sfc_port *port) +{ + return port->promisc; +} + +static boolean_t +sfc_get_requested_all_mcast(struct sfc_port *port) +{ + return port->promisc || port->allmulti; +} + +int +sfc_set_rx_mode_unchecked(struct sfc_adapter *sa) +{ + struct sfc_port *port = &sa->port; + boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port); + boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port); + int rc; + + rc = efx_mac_filter_set(sa->nic, requested_all_ucast, B_TRUE, + requested_all_mcast, B_TRUE); + if (rc != 0) + return rc; + + return 0; +} + int sfc_set_rx_mode(struct sfc_adapter *sa) { struct sfc_port *port = &sa->port; + boolean_t old_all_ucast; + boolean_t old_all_mcast; + boolean_t requested_all_ucast = sfc_get_requested_all_ucast(port); + boolean_t requested_all_mcast = sfc_get_requested_all_mcast(port); + boolean_t actual_all_ucast; + boolean_t actual_all_mcast; int rc; - rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE, - port->promisc || port->allmulti, B_TRUE); + efx_mac_filter_get_all_ucast_mcast(sa->nic, &old_all_ucast, + &old_all_mcast); - return rc; + rc = sfc_set_rx_mode_unchecked(sa); + if (rc != 0) + return rc; + + efx_mac_filter_get_all_ucast_mcast(sa->nic, &actual_all_ucast, + &actual_all_mcast); + + if (actual_all_ucast != requested_all_ucast || + actual_all_mcast != requested_all_mcast) { + /* + * MAC filter set succeeded but not all requested modes + * were applied. The rollback is necessary to bring back the + * consistent old state. + */ + (void)efx_mac_filter_set(sa->nic, old_all_ucast, B_TRUE, + old_all_mcast, B_TRUE); + + return EPERM; + } + + return 0; } void @@ -470,10 +592,22 @@ sfc_port_link_mode_to_info(efx_link_mode_t link_mode, link_info->link_speed = ETH_SPEED_NUM_10G; link_info->link_duplex = ETH_LINK_FULL_DUPLEX; break; + case EFX_LINK_25000FDX: + link_info->link_speed = ETH_SPEED_NUM_25G; + link_info->link_duplex = ETH_LINK_FULL_DUPLEX; + break; case EFX_LINK_40000FDX: link_info->link_speed = ETH_SPEED_NUM_40G; link_info->link_duplex = ETH_LINK_FULL_DUPLEX; break; + case EFX_LINK_50000FDX: + link_info->link_speed = ETH_SPEED_NUM_50G; + link_info->link_duplex = ETH_LINK_FULL_DUPLEX; + break; + case EFX_LINK_100000FDX: + link_info->link_speed = ETH_SPEED_NUM_100G; + link_info->link_duplex = ETH_LINK_FULL_DUPLEX; + break; default: SFC_ASSERT(B_FALSE); /* FALLTHROUGH */