-/*-
- * BSD LICENSE
+/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright (c) 2016-2017 Solarflare Communications Inc.
+ * Copyright (c) 2016-2018 Solarflare Communications Inc.
* All rights reserved.
*
* This software was jointly developed between OKTET Labs (under contract
* for Solarflare) and Solarflare Communications, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "efx.h"
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)
{
uint32_t phy_adv_cap;
const uint32_t phy_pause_caps =
((1u << EFX_PHY_CAP_PAUSE) | (1u << EFX_PHY_CAP_ASYM));
+ unsigned int i;
sfc_log_init(sa, "entry");
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,
goto fail_mac_pdu_set;
if (!port->isolated) {
- struct ether_addr *mac_addrs = sa->eth_dev->data->mac_addrs;
+ struct ether_addr *addr = &port->default_mac_addr;
sfc_log_init(sa, "set MAC address");
- rc = efx_mac_addr_set(sa->nic, mac_addrs[0].addr_bytes);
+ rc = efx_mac_addr_set(sa->nic, addr->addr_bytes);
if (rc != 0)
goto fail_mac_addr_set;
efx_mac_stats_get_mask(sa->nic, port->mac_stats_mask,
sizeof(port->mac_stats_mask));
+ for (i = 0, port->mac_stats_nb_supported = 0; i < EFX_MAC_NSTATS; ++i)
+ if (EFX_MAC_STAT_SUPPORTED(port->mac_stats_mask, i))
+ port->mac_stats_nb_supported++;
+
port->mac_stats_update_generation = 0;
if (port->mac_stats_update_period_ms != 0) {
}
}
+ if ((port->mac_stats_update_period_ms != 0) &&
+ port->mac_stats_periodic_dma_supported) {
+ /*
+ * Request an explicit MAC stats upload immediately to
+ * preclude bogus figures readback if the user decides
+ * to read stats before periodic DMA is really started
+ */
+ rc = efx_mac_stats_upload(sa->nic, &port->mac_stats_dma_mem);
+ if (rc != 0)
+ goto fail_mac_stats_upload;
+ }
+
sfc_log_init(sa, "disable MAC drain");
rc = efx_mac_drain(sa->nic, B_FALSE);
if (rc != 0)
(void)efx_mac_drain(sa->nic, B_TRUE);
fail_mac_drain:
+fail_mac_stats_upload:
(void)efx_mac_stats_periodic(sa->nic, &port->mac_stats_dma_mem,
0, B_FALSE);
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:
{
const struct rte_eth_dev_data *dev_data = sa->eth_dev->data;
struct sfc_port *port = &sa->port;
+ const struct rte_eth_rxmode *rxmode = &dev_data->dev_conf.rxmode;
sfc_log_init(sa, "entry");
- if (dev_data->dev_conf.rxmode.jumbo_frame)
- port->pdu = dev_data->dev_conf.rxmode.max_rx_pkt_len;
+ if (rxmode->offloads & DEV_RX_OFFLOAD_JUMBO_FRAME)
+ port->pdu = rxmode->max_rx_pkt_len;
else
port->pdu = EFX_MAC_PDU(dev_data->mtu);
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;
+ uint32_t mac_nstats;
+ size_t mac_stats_size;
long kvarg_stats_update_period_ms;
int rc;
port->flow_ctrl = EFX_FCNTL_RESPOND | EFX_FCNTL_GENERATE;
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);
+
port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
port->nb_mcast_addrs = 0;
port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
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;
return 0;
fail_kvarg_stats_update_period_ms:
+ sfc_dma_free(sa, &port->mac_stats_dma_mem);
+
fail_mac_stats_dma_alloc:
rte_free(port->mac_stats_buf);
+
fail_mac_stats_buf_alloc:
+ rte_free(port->mcast_addrs);
+
fail_mcast_addr_list_buf_alloc:
sfc_log_init(sa, "failed %d", rc);
return rc;
sfc_dma_free(sa, &port->mac_stats_dma_mem);
rte_free(port->mac_stats_buf);
+ rte_free(port->mcast_addrs);
+
sfc_log_init(sa, "done");
}
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 */