/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2015-2020
+ * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
+ * Copyright(c) 2010-2017 Intel Corporation
*/
#include <stdio.h>
#include <rte_memory.h>
#include <rte_eal.h>
#include <rte_alarm.h>
+#include <rte_kvargs.h>
#include "txgbe_logs.h"
#include "base/txgbe.h"
static void txgbe_dev_link_status_print(struct rte_eth_dev *dev);
static int txgbe_dev_lsc_interrupt_setup(struct rte_eth_dev *dev, uint8_t on);
static int txgbe_dev_macsec_interrupt_setup(struct rte_eth_dev *dev);
+static int txgbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev);
static int txgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev);
static int txgbe_dev_interrupt_get_status(struct rte_eth_dev *dev);
static int txgbe_dev_interrupt_action(struct rte_eth_dev *dev,
* The set of PCI devices this driver supports
*/
static const struct rte_pci_id pci_id_txgbe_map[] = {
- { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_RAPTOR_SFP) },
- { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_WX1820_SFP) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_SP1000) },
+ { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_WX1820) },
{ .vendor_id = 0, /* sentinel */ },
};
hw->mac.release_swfw_sync(hw, mask);
}
+static int
+txgbe_handle_devarg(__rte_unused const char *key, const char *value,
+ void *extra_args)
+{
+ uint16_t *n = extra_args;
+
+ if (value == NULL || extra_args == NULL)
+ return -EINVAL;
+
+ *n = (uint16_t)strtoul(value, NULL, 10);
+ if (*n == USHRT_MAX && errno == ERANGE)
+ return -1;
+
+ return 0;
+}
+
+static void
+txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+ u16 auto_neg = 1;
+ u16 poll = 0;
+ u16 present = 1;
+ u16 sgmii = 0;
+ u16 ffe_set = 0;
+ u16 ffe_main = 27;
+ u16 ffe_pre = 8;
+ u16 ffe_post = 44;
+
+ if (devargs == NULL)
+ goto null;
+
+ kvlist = rte_kvargs_parse(devargs->args, txgbe_valid_arguments);
+ if (kvlist == NULL)
+ goto null;
+
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_AUTO,
+ &txgbe_handle_devarg, &auto_neg);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_POLL,
+ &txgbe_handle_devarg, &poll);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_PRESENT,
+ &txgbe_handle_devarg, &present);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_KX_SGMII,
+ &txgbe_handle_devarg, &sgmii);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_SET,
+ &txgbe_handle_devarg, &ffe_set);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_MAIN,
+ &txgbe_handle_devarg, &ffe_main);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_PRE,
+ &txgbe_handle_devarg, &ffe_pre);
+ rte_kvargs_process(kvlist, TXGBE_DEVARG_FFE_POST,
+ &txgbe_handle_devarg, &ffe_post);
+ rte_kvargs_free(kvlist);
+
+null:
+ hw->devarg.auto_neg = auto_neg;
+ hw->devarg.poll = poll;
+ hw->devarg.present = present;
+ hw->devarg.sgmii = sgmii;
+ hw->phy.ffe_set = ffe_set;
+ hw->phy.ffe_main = ffe_main;
+ hw->phy.ffe_pre = ffe_pre;
+ hw->phy.ffe_post = ffe_post;
+}
+
static int
eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
{
hw->isb_dma = TMZ_PADDR(mz);
hw->isb_mem = TMZ_VADDR(mz);
+ txgbe_parse_devargs(hw, pci_dev->device.devargs);
/* Initialize the shared code (base driver) */
err = txgbe_init_shared_code(hw);
if (err != 0) {
eth_txgbe_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
struct rte_pci_device *pci_dev)
{
- struct rte_eth_dev *pf_ethdev;
- struct rte_eth_devargs eth_da;
- int retval;
-
- if (pci_dev->device.devargs) {
- retval = rte_eth_devargs_parse(pci_dev->device.devargs->args,
- ð_da);
- if (retval)
- return retval;
- } else {
- memset(ð_da, 0, sizeof(eth_da));
- }
-
- retval = rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
+ return rte_eth_dev_create(&pci_dev->device, pci_dev->device.name,
sizeof(struct txgbe_adapter),
eth_dev_pci_specific_init, pci_dev,
eth_txgbe_dev_init, NULL);
-
- if (retval || eth_da.nb_representor_ports < 1)
- return retval;
-
- pf_ethdev = rte_eth_dev_allocated(pci_dev->device.name);
- if (pf_ethdev == NULL)
- return -ENODEV;
-
- return 0;
}
static int eth_txgbe_pci_remove(struct rte_pci_device *pci_dev)
ethdev = rte_eth_dev_allocated(pci_dev->device.name);
if (!ethdev)
- return -ENODEV;
+ return 0;
return rte_eth_dev_destroy(ethdev, eth_txgbe_dev_uninit);
}
ctrl = rd32(hw, TXGBE_PORTCTL);
ctrl &= ~TXGBE_PORTCTL_VLANEXT;
- ctrl &= ~TXGBE_PORTCTL_QINQ;
wr32(hw, TXGBE_PORTCTL, ctrl);
}
txgbe_vlan_hw_extend_enable(struct rte_eth_dev *dev)
{
struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
- struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
- struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
uint32_t ctrl;
PMD_INIT_FUNC_TRACE();
ctrl = rd32(hw, TXGBE_PORTCTL);
ctrl |= TXGBE_PORTCTL_VLANEXT;
- if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP ||
- txmode->offloads & DEV_TX_OFFLOAD_QINQ_INSERT)
- ctrl |= TXGBE_PORTCTL_QINQ;
+ wr32(hw, TXGBE_PORTCTL, ctrl);
+}
+
+static void
+txgbe_qinq_hw_strip_disable(struct rte_eth_dev *dev)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ uint32_t ctrl;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ctrl = rd32(hw, TXGBE_PORTCTL);
+ ctrl &= ~TXGBE_PORTCTL_QINQ;
+ wr32(hw, TXGBE_PORTCTL, ctrl);
+}
+
+static void
+txgbe_qinq_hw_strip_enable(struct rte_eth_dev *dev)
+{
+ struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+ uint32_t ctrl;
+
+ PMD_INIT_FUNC_TRACE();
+
+ ctrl = rd32(hw, TXGBE_PORTCTL);
+ ctrl |= TXGBE_PORTCTL_QINQ | TXGBE_PORTCTL_VLANEXT;
wr32(hw, TXGBE_PORTCTL, ctrl);
}
txgbe_vlan_hw_extend_disable(dev);
}
+ if (mask & ETH_QINQ_STRIP_MASK) {
+ if (rxmode->offloads & DEV_RX_OFFLOAD_QINQ_STRIP)
+ txgbe_qinq_hw_strip_enable(dev);
+ else
+ txgbe_qinq_hw_strip_disable(dev);
+ }
+
return 0;
}
gpie |= TXGBE_GPIOBIT_6;
wr32(hw, TXGBE_GPIOINTEN, gpie);
intr->mask_misc |= TXGBE_ICRMISC_GPIO;
+ intr->mask_misc |= TXGBE_ICRMISC_ANDONE;
}
int
hw->mac.enable_tx_laser(hw);
}
- err = hw->mac.check_link(hw, &speed, &link_up, 0);
+ if ((hw->subsystem_device_id & 0xFF) != TXGBE_DEV_ID_KR_KX_KX4)
+ err = hw->mac.check_link(hw, &speed, &link_up, 0);
if (err)
goto error;
dev->data->dev_link.link_status = link_up;
skip_link_setup:
if (rte_intr_allow_others(intr_handle)) {
+ txgbe_dev_misc_interrupt_setup(dev);
/* check if lsc interrupt is enabled */
if (dev->data->dev_conf.intr_conf.lsc != 0)
txgbe_dev_lsc_interrupt_setup(dev, TRUE);
hw_stats->rx_bytes += rd64(hw, TXGBE_DMARXOCTL);
hw_stats->tx_bytes += rd64(hw, TXGBE_DMATXOCTL);
+ hw_stats->rx_dma_drop += rd32(hw, TXGBE_DMARXDROP);
hw_stats->rx_drop_packets += rd32(hw, TXGBE_PBRXDROP);
/* MAC Stats */
}
/* Rx Errors */
- stats->imissed = hw_stats->rx_total_missed_packets;
+ stats->imissed = hw_stats->rx_total_missed_packets +
+ hw_stats->rx_dma_drop;
stats->ierrors = hw_stats->rx_crc_errors +
hw_stats->rx_mac_short_packet_dropped +
hw_stats->rx_length_errors +
txgbe_fw_version_get(struct rte_eth_dev *dev, char *fw_version, size_t fw_size)
{
struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
- u16 eeprom_verh, eeprom_verl;
u32 etrack_id;
int ret;
- hw->rom.readw_sw(hw, TXGBE_EEPROM_VERSION_H, &eeprom_verh);
- hw->rom.readw_sw(hw, TXGBE_EEPROM_VERSION_L, &eeprom_verl);
+ hw->phy.get_fw_version(hw, &etrack_id);
- etrack_id = (eeprom_verh << 16) | eeprom_verl;
ret = snprintf(fw_version, fw_size, "0x%08x", etrack_id);
+ if (ret < 0)
+ return -EINVAL;
ret += 1; /* add the size of '\0' */
- if (fw_size < (u32)ret)
+ if (fw_size < (size_t)ret)
return ret;
else
return 0;
}
if (link_up == 0) {
- if (hw->phy.media_type == txgbe_media_type_fiber) {
+ if ((hw->subsystem_device_id & 0xFF) ==
+ TXGBE_DEV_ID_KR_KX_KX4) {
+ hw->mac.bp_down_event(hw);
+ } else if (hw->phy.media_type == txgbe_media_type_fiber) {
intr->flags |= TXGBE_FLAG_NEED_LINK_CONFIG;
rte_eal_alarm_set(10,
txgbe_dev_setup_link_alarm_handler, dev);
return 0;
}
+static int
+txgbe_dev_misc_interrupt_setup(struct rte_eth_dev *dev)
+{
+ struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+ u64 mask;
+
+ mask = TXGBE_ICR_MASK;
+ mask &= (1ULL << TXGBE_MISC_VEC_ID);
+ intr->mask |= mask;
+ intr->mask_misc |= TXGBE_ICRMISC_GPIO;
+ intr->mask_misc |= TXGBE_ICRMISC_ANDONE;
+ return 0;
+}
+
/**
* It clears the interrupt causes and enables the interrupt.
* It will be called once only during nic initialized.
txgbe_dev_rxq_interrupt_setup(struct rte_eth_dev *dev)
{
struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev);
+ u64 mask;
- intr->mask[0] |= TXGBE_ICR_MASK;
- intr->mask[1] |= TXGBE_ICR_MASK;
+ mask = TXGBE_ICR_MASK;
+ mask &= ~((1ULL << TXGBE_RX_VEC_START) - 1);
+ intr->mask |= mask;
return 0;
}
if (eicr & TXGBE_ICRMISC_LSC)
intr->flags |= TXGBE_FLAG_NEED_LINK_UPDATE;
+ if (eicr & TXGBE_ICRMISC_ANDONE)
+ intr->flags |= TXGBE_FLAG_NEED_AN_CONFIG;
+
if (eicr & TXGBE_ICRMISC_VFMBX)
intr->flags |= TXGBE_FLAG_MAILBOX;
intr->flags &= ~TXGBE_FLAG_PHY_INTERRUPT;
}
+ if (intr->flags & TXGBE_FLAG_NEED_AN_CONFIG) {
+ if (hw->devarg.auto_neg == 1 && hw->devarg.poll == 0) {
+ hw->mac.kr_handle(hw);
+ intr->flags &= ~TXGBE_FLAG_NEED_AN_CONFIG;
+ }
+ }
+
if (intr->flags & TXGBE_FLAG_NEED_LINK_UPDATE) {
struct rte_eth_link link;
/* handle it 1 sec later, wait it being stable */
timeout = TXGBE_LINK_UP_CHECK_TIMEOUT;
/* likely to down */
+ else if ((hw->subsystem_device_id & 0xFF) ==
+ TXGBE_DEV_ID_KR_KX_KX4 &&
+ hw->devarg.auto_neg == 1)
+ /* handle it 2 sec later for backplane AN73 */
+ timeout = 2000;
else
/* handle it 4 sec later, wait it being stable */
timeout = TXGBE_LINK_DOWN_CHECK_TIMEOUT;
(void *)dev) < 0) {
PMD_DRV_LOG(ERR, "Error setting alarm");
} else {
- /* remember original mask */
- intr->mask_misc_orig = intr->mask_misc;
/* only disable lsc interrupt */
intr->mask_misc &= ~TXGBE_ICRMISC_LSC;
+
+ intr->mask_orig = intr->mask;
+ /* only disable all misc interrupts */
+ intr->mask &= ~(1ULL << TXGBE_MISC_VEC_ID);
}
}
}
/* restore original mask */
- intr->mask_misc = intr->mask_misc_orig;
- intr->mask_misc_orig = 0;
+ intr->mask_misc |= TXGBE_ICRMISC_LSC;
+
+ intr->mask = intr->mask_orig;
+ intr->mask_orig = 0;
PMD_DRV_LOG(DEBUG, "enable intr in delayed handler S[%08x]", eicr);
txgbe_enable_intr(dev);
}
static int
-txgbe_dev_filter_ctrl(__rte_unused struct rte_eth_dev *dev,
- enum rte_filter_type filter_type,
- enum rte_filter_op filter_op,
- void *arg)
+txgbe_dev_flow_ops_get(__rte_unused struct rte_eth_dev *dev,
+ const struct rte_flow_ops **ops)
{
- int ret = 0;
-
- switch (filter_type) {
- case RTE_ETH_FILTER_GENERIC:
- if (filter_op != RTE_ETH_FILTER_GET)
- return -EINVAL;
- *(const void **)arg = &txgbe_flow_ops;
- break;
- default:
- PMD_DRV_LOG(WARNING, "Filter type (%d) not supported",
- filter_type);
- ret = -EINVAL;
- break;
- }
-
- return ret;
+ *ops = &txgbe_flow_ops;
+ return 0;
}
static u8 *
hw = TXGBE_DEV_HW(dev);
mc_addr_list = (u8 *)mc_addr_set;
- return txgbe_update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,
+ return hw->mac.update_mc_addr_list(hw, mc_addr_list, nb_mc_addr,
txgbe_dev_addr_list_itr, TRUE);
}
break;
}
wr32(hw, TXGBE_VXLANPORT, udp_tunnel->udp_port);
- wr32(hw, TXGBE_VXLANPORTGPE, udp_tunnel->udp_port);
break;
case RTE_TUNNEL_TYPE_GENEVE:
if (udp_tunnel->udp_port == 0) {
}
wr32(hw, TXGBE_TEREDOPORT, udp_tunnel->udp_port);
break;
+ case RTE_TUNNEL_TYPE_VXLAN_GPE:
+ if (udp_tunnel->udp_port == 0) {
+ PMD_DRV_LOG(ERR, "Add VxLAN port 0 is not allowed.");
+ ret = -EINVAL;
+ break;
+ }
+ wr32(hw, TXGBE_VXLANPORTGPE, udp_tunnel->udp_port);
+ break;
default:
PMD_DRV_LOG(ERR, "Invalid tunnel type");
ret = -EINVAL;
break;
}
wr32(hw, TXGBE_VXLANPORT, 0);
- wr32(hw, TXGBE_VXLANPORTGPE, 0);
break;
case RTE_TUNNEL_TYPE_GENEVE:
cur_port = (uint16_t)rd32(hw, TXGBE_GENEVEPORT);
}
wr32(hw, TXGBE_TEREDOPORT, 0);
break;
+ case RTE_TUNNEL_TYPE_VXLAN_GPE:
+ cur_port = (uint16_t)rd32(hw, TXGBE_VXLANPORTGPE);
+ if (cur_port != udp_tunnel->udp_port) {
+ PMD_DRV_LOG(ERR, "Port %u does not exist.",
+ udp_tunnel->udp_port);
+ ret = -EINVAL;
+ break;
+ }
+ wr32(hw, TXGBE_VXLANPORTGPE, 0);
+ break;
default:
PMD_DRV_LOG(ERR, "Invalid tunnel type");
ret = -EINVAL;
.reta_query = txgbe_dev_rss_reta_query,
.rss_hash_update = txgbe_dev_rss_hash_update,
.rss_hash_conf_get = txgbe_dev_rss_hash_conf_get,
- .filter_ctrl = txgbe_dev_filter_ctrl,
+ .flow_ops_get = txgbe_dev_flow_ops_get,
.set_mc_addr_list = txgbe_dev_set_mc_addr_list,
.rxq_info_get = txgbe_rxq_info_get,
.txq_info_get = txgbe_txq_info_get,
RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd);
RTE_PMD_REGISTER_PCI_TABLE(net_txgbe, pci_id_txgbe_map);
RTE_PMD_REGISTER_KMOD_DEP(net_txgbe, "* igb_uio | uio_pci_generic | vfio-pci");
-
-RTE_LOG_REGISTER(txgbe_logtype_init, pmd.net.txgbe.init, NOTICE);
-RTE_LOG_REGISTER(txgbe_logtype_driver, pmd.net.txgbe.driver, NOTICE);
+RTE_PMD_REGISTER_PARAM_STRING(net_txgbe,
+ TXGBE_DEVARG_BP_AUTO "=<0|1>"
+ TXGBE_DEVARG_KR_POLL "=<0|1>"
+ TXGBE_DEVARG_KR_PRESENT "=<0|1>"
+ TXGBE_DEVARG_KX_SGMII "=<0|1>"
+ TXGBE_DEVARG_FFE_SET "=<0-4>"
+ TXGBE_DEVARG_FFE_MAIN "=<uint16>"
+ TXGBE_DEVARG_FFE_PRE "=<uint16>"
+ TXGBE_DEVARG_FFE_POST "=<uint16>");
+
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_init, init, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_driver, driver, NOTICE);
+RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_bp, bp, NOTICE);
#ifdef RTE_LIBRTE_TXGBE_DEBUG_RX
- RTE_LOG_REGISTER(txgbe_logtype_rx, pmd.net.txgbe.rx, DEBUG);
+ RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_rx, rx, DEBUG);
#endif
#ifdef RTE_LIBRTE_TXGBE_DEBUG_TX
- RTE_LOG_REGISTER(txgbe_logtype_tx, pmd.net.txgbe.tx, DEBUG);
+ RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_tx, tx, DEBUG);
#endif
#ifdef RTE_LIBRTE_TXGBE_DEBUG_TX_FREE
- RTE_LOG_REGISTER(txgbe_logtype_tx_free, pmd.net.txgbe.tx_free, DEBUG);
+ RTE_LOG_REGISTER_SUFFIX(txgbe_logtype_tx_free, tx_free, DEBUG);
#endif