#include "sfc_ev.h"
#include "sfc_rx.h"
#include "sfc_tx.h"
-
+#include "sfc_flow.h"
static void
sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
}
#endif
+ if (sa->tso)
+ dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO;
+
dev_info->rx_desc_lim.nb_max = EFX_RXQ_MAXNDESCS;
dev_info->rx_desc_lim.nb_min = EFX_RXQ_MINNDESCS;
/* The RXQ hardware requires that the descriptor count is a power
sfc_log_init(sa, "entry");
- if (sa->state != SFC_ADAPTER_STARTED)
- return 0;
-
retry:
EFX_STATIC_ASSERT(sizeof(*dev_link) == sizeof(rte_atomic64_t));
*(int64_t *)&old_link = rte_atomic64_read((rte_atomic64_t *)dev_link);
- if (wait_to_complete) {
+ if (sa->state != SFC_ADAPTER_STARTED) {
+ sfc_port_link_mode_to_info(EFX_LINK_UNKNOWN, ¤t_link);
+ if (!rte_atomic64_cmpset((volatile uint64_t *)dev_link,
+ *(uint64_t *)&old_link,
+ *(uint64_t *)¤t_link))
+ goto retry;
+ } else if (wait_to_complete) {
efx_link_mode_t link_mode;
- efx_port_poll(sa->nic, &link_mode);
+ if (efx_port_poll(sa->nic, &link_mode) != 0)
+ link_mode = EFX_LINK_UNKNOWN;
sfc_port_link_mode_to_info(link_mode, ¤t_link);
if (!rte_atomic64_cmpset((volatile uint64_t *)dev_link,
rte_spinlock_unlock(&port->mac_stats_lock);
}
+static void
+sfc_stats_reset(struct rte_eth_dev *dev)
+{
+ struct sfc_adapter *sa = dev->data->dev_private;
+ struct sfc_port *port = &sa->port;
+ int rc;
+
+ if (sa->state != SFC_ADAPTER_STARTED) {
+ /*
+ * The operation cannot be done if port is not started; it
+ * will be scheduled to be done during the next port start
+ */
+ port->mac_stats_reset_pending = B_TRUE;
+ return;
+ }
+
+ rc = sfc_port_reset_mac_stats(sa);
+ if (rc != 0)
+ sfc_err(sa, "failed to reset statistics (rc = %d)", rc);
+}
+
static int
sfc_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
unsigned int xstats_count)
uint32_t nb_mc_addr)
{
struct sfc_adapter *sa = dev->data->dev_private;
- uint8_t *mc_addrs_p;
- uint8_t *mc_addrs;
+ uint8_t *mc_addrs_p = NULL;
int rc;
unsigned int i;
return -EINVAL;
}
- mc_addrs_p = rte_calloc("mc-addrs", nb_mc_addr, EFX_MAC_ADDR_LEN, 0);
- if (mc_addrs_p == NULL)
- return -ENOMEM;
+ if (nb_mc_addr != 0) {
+ uint8_t *mc_addrs;
- mc_addrs = mc_addrs_p;
+ mc_addrs_p = rte_calloc("mc-addrs", nb_mc_addr,
+ EFX_MAC_ADDR_LEN, 0);
+ if (mc_addrs_p == NULL)
+ return -ENOMEM;
- for (i = 0; i < nb_mc_addr; ++i) {
- (void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes,
- EFX_MAC_ADDR_LEN);
- mc_addrs += EFX_MAC_ADDR_LEN;
+ mc_addrs = mc_addrs_p;
+ for (i = 0; i < nb_mc_addr; ++i) {
+ (void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes,
+ EFX_MAC_ADDR_LEN);
+ mc_addrs += EFX_MAC_ADDR_LEN;
+ }
}
rc = efx_mac_multicast_list_set(sa->nic, mc_addrs_p, nb_mc_addr);
return 0;
}
+
+static int
+sfc_dev_rss_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct sfc_adapter *sa = dev->data->dev_private;
+ unsigned int *rss_tbl_new;
+ uint16_t entry;
+ int rc;
+
+
+ if ((sa->rss_channels == 1) ||
+ (sa->rss_support != EFX_RX_SCALE_EXCLUSIVE)) {
+ sfc_err(sa, "RSS is not available");
+ return -ENOTSUP;
+ }
+
+ if (reta_size != EFX_RSS_TBL_SIZE) {
+ sfc_err(sa, "RETA size is wrong (should be %u)",
+ EFX_RSS_TBL_SIZE);
+ return -EINVAL;
+ }
+
+ rss_tbl_new = rte_zmalloc("rss_tbl_new", sizeof(sa->rss_tbl), 0);
+ if (rss_tbl_new == NULL)
+ return -ENOMEM;
+
+ sfc_adapter_lock(sa);
+
+ rte_memcpy(rss_tbl_new, sa->rss_tbl, sizeof(sa->rss_tbl));
+
+ for (entry = 0; entry < reta_size; entry++) {
+ int grp_idx = entry % RTE_RETA_GROUP_SIZE;
+ struct rte_eth_rss_reta_entry64 *grp;
+
+ grp = &reta_conf[entry / RTE_RETA_GROUP_SIZE];
+
+ if (grp->mask & (1ull << grp_idx)) {
+ if (grp->reta[grp_idx] >= sa->rss_channels) {
+ rc = EINVAL;
+ goto bad_reta_entry;
+ }
+ rss_tbl_new[entry] = grp->reta[grp_idx];
+ }
+ }
+
+ rc = efx_rx_scale_tbl_set(sa->nic, rss_tbl_new, EFX_RSS_TBL_SIZE);
+ if (rc == 0)
+ rte_memcpy(sa->rss_tbl, rss_tbl_new, sizeof(sa->rss_tbl));
+
+bad_reta_entry:
+ sfc_adapter_unlock(sa);
+
+ rte_free(rss_tbl_new);
+
+ SFC_ASSERT(rc >= 0);
+ return -rc;
+}
#endif
+static int
+sfc_dev_filter_ctrl(struct rte_eth_dev *dev, enum rte_filter_type filter_type,
+ enum rte_filter_op filter_op,
+ void *arg)
+{
+ struct sfc_adapter *sa = dev->data->dev_private;
+ int rc = ENOTSUP;
+
+ sfc_log_init(sa, "entry");
+
+ switch (filter_type) {
+ case RTE_ETH_FILTER_NONE:
+ sfc_err(sa, "Global filters configuration not supported");
+ break;
+ case RTE_ETH_FILTER_MACVLAN:
+ sfc_err(sa, "MACVLAN filters not supported");
+ break;
+ case RTE_ETH_FILTER_ETHERTYPE:
+ sfc_err(sa, "EtherType filters not supported");
+ break;
+ case RTE_ETH_FILTER_FLEXIBLE:
+ sfc_err(sa, "Flexible filters not supported");
+ break;
+ case RTE_ETH_FILTER_SYN:
+ sfc_err(sa, "SYN filters not supported");
+ break;
+ case RTE_ETH_FILTER_NTUPLE:
+ sfc_err(sa, "NTUPLE filters not supported");
+ break;
+ case RTE_ETH_FILTER_TUNNEL:
+ sfc_err(sa, "Tunnel filters not supported");
+ break;
+ case RTE_ETH_FILTER_FDIR:
+ sfc_err(sa, "Flow Director filters not supported");
+ break;
+ case RTE_ETH_FILTER_HASH:
+ sfc_err(sa, "Hash filters not supported");
+ break;
+ case RTE_ETH_FILTER_GENERIC:
+ if (filter_op != RTE_ETH_FILTER_GET) {
+ rc = EINVAL;
+ } else {
+ *(const void **)arg = &sfc_flow_ops;
+ rc = 0;
+ }
+ break;
+ default:
+ sfc_err(sa, "Unknown filter type %u", filter_type);
+ break;
+ }
+
+ sfc_log_init(sa, "exit: %d", -rc);
+ SFC_ASSERT(rc >= 0);
+ return -rc;
+}
+
static const struct eth_dev_ops sfc_eth_dev_ops = {
.dev_configure = sfc_dev_configure,
.dev_start = sfc_dev_start,
.allmulticast_disable = sfc_dev_allmulti_disable,
.link_update = sfc_dev_link_update,
.stats_get = sfc_stats_get,
+ .stats_reset = sfc_stats_reset,
.xstats_get = sfc_xstats_get,
+ .xstats_reset = sfc_stats_reset,
.xstats_get_names = sfc_xstats_get_names,
.dev_infos_get = sfc_dev_infos_get,
.dev_supported_ptypes_get = sfc_dev_supported_ptypes_get,
.flow_ctrl_set = sfc_flow_ctrl_set,
.mac_addr_set = sfc_mac_addr_set,
#if EFSYS_OPT_RX_SCALE
+ .reta_update = sfc_dev_rss_reta_update,
.reta_query = sfc_dev_rss_reta_query,
.rss_hash_update = sfc_dev_rss_hash_update,
.rss_hash_conf_get = sfc_dev_rss_hash_conf_get,
#endif
+ .filter_ctrl = sfc_dev_filter_ctrl,
.set_mc_addr_list = sfc_set_mc_addr_list,
.rxq_info_get = sfc_rx_queue_info_get,
.txq_info_get = sfc_tx_queue_info_get,
RTE_PMD_REGISTER_PCI(net_sfc_efx, sfc_efx_pmd.pci_drv);
RTE_PMD_REGISTER_PCI_TABLE(net_sfc_efx, pci_id_sfc_efx_map);
+RTE_PMD_REGISTER_KMOD_DEP(net_sfc_efx, "* igb_uio | uio_pci_generic | vfio");
RTE_PMD_REGISTER_PARAM_STRING(net_sfc_efx,
SFC_KVARG_PERF_PROFILE "=" SFC_KVARG_VALUES_PERF_PROFILE " "
SFC_KVARG_MCDI_LOGGING "=" SFC_KVARG_VALUES_BOOL " "