numam-dpdk/drivers/net/ixgbe/rte_pmd_ixgbe.c
Shweta Choudaha c2071c19ad net/ixgbe: add API to update SBP bit
Add ixgbe API to enable SBP bit in FCTRL register
to allow receiving packets that may otherwise be
considered length errors by ixgbe and dropped

Signed-off-by: Shweta Choudaha <shweta.choudaha@att.com>
Reviewed-by: Chas Williams <chas3@att.com>
Reviewed-by: Luca Boccassi <bluca@debian.org>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
2018-05-14 22:31:47 +01:00

1245 lines
28 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2010-2017 Intel Corporation
*/
#include <rte_ethdev_driver.h>
#include "base/ixgbe_api.h"
#include "base/ixgbe_x550.h"
#include "ixgbe_ethdev.h"
#include "rte_pmd_ixgbe.h"
int
rte_pmd_ixgbe_set_vf_mac_addr(uint16_t port, uint16_t vf,
struct ether_addr *mac_addr)
{
struct ixgbe_hw *hw;
struct ixgbe_vf_info *vfinfo;
int rar_entry;
uint8_t *new_mac = (uint8_t *)(mac_addr);
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
rar_entry = hw->mac.num_rar_entries - (vf + 1);
if (is_valid_assigned_ether_addr((struct ether_addr *)new_mac)) {
rte_memcpy(vfinfo[vf].vf_mac_addresses, new_mac,
ETHER_ADDR_LEN);
return hw->mac.ops.set_rar(hw, rar_entry, new_mac, vf,
IXGBE_RAH_AV);
}
return -EINVAL;
}
int
rte_pmd_ixgbe_ping_vf(uint16_t port, uint16_t vf)
{
struct ixgbe_hw *hw;
struct ixgbe_vf_info *vfinfo;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
uint32_t ctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
vfinfo = *(IXGBE_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private));
ctrl = IXGBE_PF_CONTROL_MSG;
if (vfinfo[vf].clear_to_send)
ctrl |= IXGBE_VT_MSGTYPE_CTS;
ixgbe_write_mbx(hw, &ctrl, 1, vf);
return 0;
}
int
rte_pmd_ixgbe_set_vf_vlan_anti_spoof(uint16_t port, uint16_t vf, uint8_t on)
{
struct ixgbe_hw *hw;
struct ixgbe_mac_info *mac;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
mac = &hw->mac;
mac->ops.set_vlan_anti_spoofing(hw, on, vf);
return 0;
}
int
rte_pmd_ixgbe_set_vf_mac_anti_spoof(uint16_t port, uint16_t vf, uint8_t on)
{
struct ixgbe_hw *hw;
struct ixgbe_mac_info *mac;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
mac = &hw->mac;
mac->ops.set_mac_anti_spoofing(hw, on, vf);
return 0;
}
int
rte_pmd_ixgbe_set_vf_vlan_insert(uint16_t port, uint16_t vf, uint16_t vlan_id)
{
struct ixgbe_hw *hw;
uint32_t ctrl;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (vlan_id > ETHER_MAX_VLAN_ID)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
ctrl = IXGBE_READ_REG(hw, IXGBE_VMVIR(vf));
if (vlan_id) {
ctrl = vlan_id;
ctrl |= IXGBE_VMVIR_VLANA_DEFAULT;
} else {
ctrl = 0;
}
IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), ctrl);
return 0;
}
int
rte_pmd_ixgbe_set_tx_loopback(uint16_t port, uint8_t on)
{
struct ixgbe_hw *hw;
uint32_t ctrl;
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
ctrl = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
/* enable or disable VMDQ loopback */
if (on)
ctrl |= IXGBE_PFDTXGSWC_VT_LBEN;
else
ctrl &= ~IXGBE_PFDTXGSWC_VT_LBEN;
IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, ctrl);
return 0;
}
int
rte_pmd_ixgbe_set_all_queues_drop_en(uint16_t port, uint8_t on)
{
struct ixgbe_hw *hw;
uint32_t reg_value;
int i;
int num_queues = (int)(IXGBE_QDE_IDX_MASK >> IXGBE_QDE_IDX_SHIFT);
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
for (i = 0; i <= num_queues; i++) {
reg_value = IXGBE_QDE_WRITE |
(i << IXGBE_QDE_IDX_SHIFT) |
(on & IXGBE_QDE_ENABLE);
IXGBE_WRITE_REG(hw, IXGBE_QDE, reg_value);
}
return 0;
}
int
rte_pmd_ixgbe_set_vf_split_drop_en(uint16_t port, uint16_t vf, uint8_t on)
{
struct ixgbe_hw *hw;
uint32_t reg_value;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
/* only support VF's 0 to 63 */
if ((vf >= pci_dev->max_vfs) || (vf > 63))
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
reg_value = IXGBE_READ_REG(hw, IXGBE_SRRCTL(vf));
if (on)
reg_value |= IXGBE_SRRCTL_DROP_EN;
else
reg_value &= ~IXGBE_SRRCTL_DROP_EN;
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(vf), reg_value);
return 0;
}
int
rte_pmd_ixgbe_set_vf_vlan_stripq(uint16_t port, uint16_t vf, uint8_t on)
{
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
struct ixgbe_hw *hw;
uint16_t queues_per_pool;
uint32_t q;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->vlan_strip_queue_set, -ENOTSUP);
/* The PF has 128 queue pairs and in SRIOV configuration
* those queues will be assigned to VF's, so RXDCTL
* registers will be dealing with queues which will be
* assigned to VF's.
* Let's say we have SRIOV configured with 31 VF's then the
* first 124 queues 0-123 will be allocated to VF's and only
* the last 4 queues 123-127 will be assigned to the PF.
*/
if (hw->mac.type == ixgbe_mac_82598EB)
queues_per_pool = (uint16_t)hw->mac.max_rx_queues /
ETH_16_POOLS;
else
queues_per_pool = (uint16_t)hw->mac.max_rx_queues /
ETH_64_POOLS;
for (q = 0; q < queues_per_pool; q++)
(*dev->dev_ops->vlan_strip_queue_set)(dev,
q + vf * queues_per_pool, on);
return 0;
}
int
rte_pmd_ixgbe_set_vf_rxmode(uint16_t port, uint16_t vf,
uint16_t rx_mask, uint8_t on)
{
int val = 0;
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
struct ixgbe_hw *hw;
uint32_t vmolr;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
if (hw->mac.type == ixgbe_mac_82598EB) {
PMD_INIT_LOG(ERR, "setting VF receive mode set should be done"
" on 82599 hardware and newer");
return -ENOTSUP;
}
if (ixgbe_vt_check(hw) < 0)
return -ENOTSUP;
val = ixgbe_convert_vm_rx_mask_to_val(rx_mask, val);
if (on)
vmolr |= val;
else
vmolr &= ~val;
IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
return 0;
}
int
rte_pmd_ixgbe_set_vf_rx(uint16_t port, uint16_t vf, uint8_t on)
{
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
uint32_t reg, addr;
uint32_t val;
const uint8_t bit1 = 0x1;
struct ixgbe_hw *hw;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (ixgbe_vt_check(hw) < 0)
return -ENOTSUP;
/* for vf >= 32, set bit in PFVFRE[1], otherwise PFVFRE[0] */
if (vf >= 32) {
addr = IXGBE_VFRE(1);
val = bit1 << (vf - 32);
} else {
addr = IXGBE_VFRE(0);
val = bit1 << vf;
}
reg = IXGBE_READ_REG(hw, addr);
if (on)
reg |= val;
else
reg &= ~val;
IXGBE_WRITE_REG(hw, addr, reg);
return 0;
}
int
rte_pmd_ixgbe_set_vf_tx(uint16_t port, uint16_t vf, uint8_t on)
{
struct rte_eth_dev *dev;
struct rte_pci_device *pci_dev;
uint32_t reg, addr;
uint32_t val;
const uint8_t bit1 = 0x1;
struct ixgbe_hw *hw;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
pci_dev = RTE_ETH_DEV_TO_PCI(dev);
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (vf >= pci_dev->max_vfs)
return -EINVAL;
if (on > 1)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (ixgbe_vt_check(hw) < 0)
return -ENOTSUP;
/* for vf >= 32, set bit in PFVFTE[1], otherwise PFVFTE[0] */
if (vf >= 32) {
addr = IXGBE_VFTE(1);
val = bit1 << (vf - 32);
} else {
addr = IXGBE_VFTE(0);
val = bit1 << vf;
}
reg = IXGBE_READ_REG(hw, addr);
if (on)
reg |= val;
else
reg &= ~val;
IXGBE_WRITE_REG(hw, addr, reg);
return 0;
}
int
rte_pmd_ixgbe_set_vf_vlan_filter(uint16_t port, uint16_t vlan,
uint64_t vf_mask, uint8_t vlan_on)
{
struct rte_eth_dev *dev;
int ret = 0;
uint16_t vf_idx;
struct ixgbe_hw *hw;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if ((vlan > ETHER_MAX_VLAN_ID) || (vf_mask == 0))
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (ixgbe_vt_check(hw) < 0)
return -ENOTSUP;
for (vf_idx = 0; vf_idx < 64; vf_idx++) {
if (vf_mask & ((uint64_t)(1ULL << vf_idx))) {
ret = hw->mac.ops.set_vfta(hw, vlan, vf_idx,
vlan_on, false);
if (ret < 0)
return ret;
}
}
return ret;
}
int
rte_pmd_ixgbe_set_vf_rate_limit(uint16_t port, uint16_t vf,
uint16_t tx_rate, uint64_t q_msk)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_set_vf_rate_limit(dev, vf, tx_rate, q_msk);
}
int
rte_pmd_ixgbe_macsec_enable(uint16_t port, uint8_t en, uint8_t rp)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
/* Stop the data paths */
if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
return -ENOTSUP;
/**
* Workaround:
* As no ixgbe_disable_sec_rx_path equivalent is
* implemented for tx in the base code, and we are
* not allowed to modify the base code in DPDK, so
* just call the hand-written one directly for now.
* The hardware support has been checked by
* ixgbe_disable_sec_rx_path().
*/
ixgbe_disable_sec_tx_path_generic(hw);
/* Enable Ethernet CRC (required by MACsec offload) */
ctrl = IXGBE_READ_REG(hw, IXGBE_HLREG0);
ctrl |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, ctrl);
/* Enable the TX and RX crypto engines */
ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
ctrl &= ~IXGBE_SECTXCTRL_SECTX_DIS;
IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
ctrl &= ~IXGBE_SECRXCTRL_SECRX_DIS;
IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
ctrl &= ~IXGBE_SECTX_MINSECIFG_MASK;
ctrl |= 0x3;
IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, ctrl);
/* Enable SA lookup */
ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
ctrl |= en ? IXGBE_LSECTXCTRL_AUTH_ENCRYPT :
IXGBE_LSECTXCTRL_AUTH;
ctrl |= IXGBE_LSECTXCTRL_AISCI;
ctrl &= ~IXGBE_LSECTXCTRL_PNTHRSH_MASK;
ctrl |= IXGBE_MACSEC_PNTHRSH & IXGBE_LSECTXCTRL_PNTHRSH_MASK;
IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
ctrl |= IXGBE_LSECRXCTRL_STRICT << IXGBE_LSECRXCTRL_EN_SHIFT;
ctrl &= ~IXGBE_LSECRXCTRL_PLSH;
if (rp)
ctrl |= IXGBE_LSECRXCTRL_RP;
else
ctrl &= ~IXGBE_LSECRXCTRL_RP;
IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
/* Start the data paths */
ixgbe_enable_sec_rx_path(hw);
/**
* Workaround:
* As no ixgbe_enable_sec_rx_path equivalent is
* implemented for tx in the base code, and we are
* not allowed to modify the base code in DPDK, so
* just call the hand-written one directly for now.
*/
ixgbe_enable_sec_tx_path_generic(hw);
return 0;
}
int
rte_pmd_ixgbe_macsec_disable(uint16_t port)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
/* Stop the data paths */
if (ixgbe_disable_sec_rx_path(hw) != IXGBE_SUCCESS)
return -ENOTSUP;
/**
* Workaround:
* As no ixgbe_disable_sec_rx_path equivalent is
* implemented for tx in the base code, and we are
* not allowed to modify the base code in DPDK, so
* just call the hand-written one directly for now.
* The hardware support has been checked by
* ixgbe_disable_sec_rx_path().
*/
ixgbe_disable_sec_tx_path_generic(hw);
/* Disable the TX and RX crypto engines */
ctrl = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
ctrl |= IXGBE_SECTXCTRL_SECTX_DIS;
IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, ctrl);
ctrl = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
ctrl |= IXGBE_SECRXCTRL_SECRX_DIS;
IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, ctrl);
/* Disable SA lookup */
ctrl = IXGBE_READ_REG(hw, IXGBE_LSECTXCTRL);
ctrl &= ~IXGBE_LSECTXCTRL_EN_MASK;
ctrl |= IXGBE_LSECTXCTRL_DISABLE;
IXGBE_WRITE_REG(hw, IXGBE_LSECTXCTRL, ctrl);
ctrl = IXGBE_READ_REG(hw, IXGBE_LSECRXCTRL);
ctrl &= ~IXGBE_LSECRXCTRL_EN_MASK;
ctrl |= IXGBE_LSECRXCTRL_DISABLE << IXGBE_LSECRXCTRL_EN_SHIFT;
IXGBE_WRITE_REG(hw, IXGBE_LSECRXCTRL, ctrl);
/* Start the data paths */
ixgbe_enable_sec_rx_path(hw);
/**
* Workaround:
* As no ixgbe_enable_sec_rx_path equivalent is
* implemented for tx in the base code, and we are
* not allowed to modify the base code in DPDK, so
* just call the hand-written one directly for now.
*/
ixgbe_enable_sec_tx_path_generic(hw);
return 0;
}
int
rte_pmd_ixgbe_macsec_config_txsc(uint16_t port, uint8_t *mac)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCL, ctrl);
ctrl = mac[4] | (mac[5] << 8);
IXGBE_WRITE_REG(hw, IXGBE_LSECTXSCH, ctrl);
return 0;
}
int
rte_pmd_ixgbe_macsec_config_rxsc(uint16_t port, uint8_t *mac, uint16_t pi)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
ctrl = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);
IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCL, ctrl);
pi = rte_cpu_to_be_16(pi);
ctrl = mac[4] | (mac[5] << 8) | (pi << 16);
IXGBE_WRITE_REG(hw, IXGBE_LSECRXSCH, ctrl);
return 0;
}
int
rte_pmd_ixgbe_macsec_select_txsa(uint16_t port, uint8_t idx, uint8_t an,
uint32_t pn, uint8_t *key)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl, i;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (idx != 0 && idx != 1)
return -EINVAL;
if (an >= 4)
return -EINVAL;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
/* Set the PN and key */
pn = rte_cpu_to_be_32(pn);
if (idx == 0) {
IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN0, pn);
for (i = 0; i < 4; i++) {
ctrl = (key[i * 4 + 0] << 0) |
(key[i * 4 + 1] << 8) |
(key[i * 4 + 2] << 16) |
(key[i * 4 + 3] << 24);
IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY0(i), ctrl);
}
} else {
IXGBE_WRITE_REG(hw, IXGBE_LSECTXPN1, pn);
for (i = 0; i < 4; i++) {
ctrl = (key[i * 4 + 0] << 0) |
(key[i * 4 + 1] << 8) |
(key[i * 4 + 2] << 16) |
(key[i * 4 + 3] << 24);
IXGBE_WRITE_REG(hw, IXGBE_LSECTXKEY1(i), ctrl);
}
}
/* Set AN and select the SA */
ctrl = (an << idx * 2) | (idx << 4);
IXGBE_WRITE_REG(hw, IXGBE_LSECTXSA, ctrl);
return 0;
}
int
rte_pmd_ixgbe_macsec_select_rxsa(uint16_t port, uint8_t idx, uint8_t an,
uint32_t pn, uint8_t *key)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t ctrl, i;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (idx != 0 && idx != 1)
return -EINVAL;
if (an >= 4)
return -EINVAL;
/* Set the PN */
pn = rte_cpu_to_be_32(pn);
IXGBE_WRITE_REG(hw, IXGBE_LSECRXPN(idx), pn);
/* Set the key */
for (i = 0; i < 4; i++) {
ctrl = (key[i * 4 + 0] << 0) |
(key[i * 4 + 1] << 8) |
(key[i * 4 + 2] << 16) |
(key[i * 4 + 3] << 24);
IXGBE_WRITE_REG(hw, IXGBE_LSECRXKEY(idx, i), ctrl);
}
/* Set the AN and validate the SA */
ctrl = an | (1 << 2);
IXGBE_WRITE_REG(hw, IXGBE_LSECRXSA(idx), ctrl);
return 0;
}
int
rte_pmd_ixgbe_set_tc_bw_alloc(uint16_t port,
uint8_t tc_num,
uint8_t *bw_weight)
{
struct rte_eth_dev *dev;
struct ixgbe_dcb_config *dcb_config;
struct ixgbe_dcb_tc_config *tc;
struct rte_eth_conf *eth_conf;
struct ixgbe_bw_conf *bw_conf;
uint8_t i;
uint8_t nb_tcs;
uint16_t sum;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
if (tc_num > IXGBE_DCB_MAX_TRAFFIC_CLASS) {
PMD_DRV_LOG(ERR, "TCs should be no more than %d.",
IXGBE_DCB_MAX_TRAFFIC_CLASS);
return -EINVAL;
}
dcb_config = IXGBE_DEV_PRIVATE_TO_DCB_CFG(dev->data->dev_private);
bw_conf = IXGBE_DEV_PRIVATE_TO_BW_CONF(dev->data->dev_private);
eth_conf = &dev->data->dev_conf;
if (eth_conf->txmode.mq_mode == ETH_MQ_TX_DCB) {
nb_tcs = eth_conf->tx_adv_conf.dcb_tx_conf.nb_tcs;
} else if (eth_conf->txmode.mq_mode == ETH_MQ_TX_VMDQ_DCB) {
if (eth_conf->tx_adv_conf.vmdq_dcb_tx_conf.nb_queue_pools ==
ETH_32_POOLS)
nb_tcs = ETH_4_TCS;
else
nb_tcs = ETH_8_TCS;
} else {
nb_tcs = 1;
}
if (nb_tcs != tc_num) {
PMD_DRV_LOG(ERR,
"Weight should be set for all %d enabled TCs.",
nb_tcs);
return -EINVAL;
}
sum = 0;
for (i = 0; i < nb_tcs; i++)
sum += bw_weight[i];
if (sum != 100) {
PMD_DRV_LOG(ERR,
"The summary of the TC weight should be 100.");
return -EINVAL;
}
for (i = 0; i < nb_tcs; i++) {
tc = &dcb_config->tc_config[i];
tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = bw_weight[i];
}
for (; i < IXGBE_DCB_MAX_TRAFFIC_CLASS; i++) {
tc = &dcb_config->tc_config[i];
tc->path[IXGBE_DCB_TX_CONFIG].bwg_percent = 0;
}
bw_conf->tc_num = nb_tcs;
return 0;
}
int __rte_experimental
rte_pmd_ixgbe_upd_fctrl_sbp(uint16_t port, int enable)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
uint32_t fctrl;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!hw)
return -ENOTSUP;
fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
/* If 'enable' set the SBP bit else clear it */
if (enable)
fctrl |= IXGBE_FCTRL_SBP;
else
fctrl &= ~(IXGBE_FCTRL_SBP);
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
return 0;
}
#ifdef RTE_LIBRTE_IXGBE_BYPASS
int
rte_pmd_ixgbe_bypass_init(uint16_t port_id)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
ixgbe_bypass_init(dev);
return 0;
}
int
rte_pmd_ixgbe_bypass_state_show(uint16_t port_id, uint32_t *state)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_state_show(dev, state);
}
int
rte_pmd_ixgbe_bypass_state_set(uint16_t port_id, uint32_t *new_state)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_state_store(dev, new_state);
}
int
rte_pmd_ixgbe_bypass_event_show(uint16_t port_id,
uint32_t event,
uint32_t *state)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_event_show(dev, event, state);
}
int
rte_pmd_ixgbe_bypass_event_store(uint16_t port_id,
uint32_t event,
uint32_t state)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_event_store(dev, event, state);
}
int
rte_pmd_ixgbe_bypass_wd_timeout_store(uint16_t port_id, uint32_t timeout)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_wd_timeout_store(dev, timeout);
}
int
rte_pmd_ixgbe_bypass_ver_show(uint16_t port_id, uint32_t *ver)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_ver_show(dev, ver);
}
int
rte_pmd_ixgbe_bypass_wd_timeout_show(uint16_t port_id, uint32_t *wd_timeout)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_wd_timeout_show(dev, wd_timeout);
}
int
rte_pmd_ixgbe_bypass_wd_reset(uint16_t port_id)
{
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
dev = &rte_eth_devices[port_id];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
return ixgbe_bypass_wd_reset(dev);
}
#endif
/**
* rte_pmd_ixgbe_acquire_swfw - Acquire SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to acquire
*
* Acquires the SWFW semaphore and get the shared phy token as needed
*/
STATIC s32 rte_pmd_ixgbe_acquire_swfw(struct ixgbe_hw *hw, u32 mask)
{
int retries = FW_PHY_TOKEN_RETRIES;
s32 status = IXGBE_SUCCESS;
while (--retries) {
status = ixgbe_acquire_swfw_semaphore(hw, mask);
if (status) {
PMD_DRV_LOG(ERR, "Get SWFW sem failed, Status = %d\n",
status);
return status;
}
status = ixgbe_get_phy_token(hw);
if (status == IXGBE_SUCCESS)
return IXGBE_SUCCESS;
if (status == IXGBE_ERR_TOKEN_RETRY)
PMD_DRV_LOG(ERR, "Get PHY token failed, Status = %d\n",
status);
ixgbe_release_swfw_semaphore(hw, mask);
if (status != IXGBE_ERR_TOKEN_RETRY) {
PMD_DRV_LOG(ERR,
"Retry get PHY token failed, Status=%d\n",
status);
return status;
}
}
PMD_DRV_LOG(ERR, "swfw acquisition retries failed!: PHY ID = 0x%08X\n",
hw->phy.id);
return status;
}
/**
* rte_pmd_ixgbe_release_swfw_sync - Release SWFW semaphore
* @hw: pointer to hardware structure
* @mask: Mask to specify which semaphore to release
*
* Releases the SWFW semaphore and puts the shared phy token as needed
*/
STATIC void rte_pmd_ixgbe_release_swfw(struct ixgbe_hw *hw, u32 mask)
{
ixgbe_put_phy_token(hw);
ixgbe_release_swfw_semaphore(hw, mask);
}
int __rte_experimental
rte_pmd_ixgbe_mdio_lock(uint16_t port)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
u32 swfw_mask;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!hw)
return -ENOTSUP;
if (hw->bus.lan_id)
swfw_mask = IXGBE_GSSR_PHY1_SM;
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
if (rte_pmd_ixgbe_acquire_swfw(hw, swfw_mask))
return IXGBE_ERR_SWFW_SYNC;
return IXGBE_SUCCESS;
}
int __rte_experimental
rte_pmd_ixgbe_mdio_unlock(uint16_t port)
{
struct rte_eth_dev *dev;
struct ixgbe_hw *hw;
u32 swfw_mask;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!hw)
return -ENOTSUP;
if (hw->bus.lan_id)
swfw_mask = IXGBE_GSSR_PHY1_SM;
else
swfw_mask = IXGBE_GSSR_PHY0_SM;
rte_pmd_ixgbe_release_swfw(hw, swfw_mask);
return IXGBE_SUCCESS;
}
int __rte_experimental
rte_pmd_ixgbe_mdio_unlocked_read(uint16_t port, uint32_t reg_addr,
uint32_t dev_type, uint16_t *phy_data)
{
struct ixgbe_hw *hw;
struct rte_eth_dev *dev;
u32 i, data, command;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!hw)
return -ENOTSUP;
/* Setup and write the read command */
command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(dev_type << IXGBE_MSCA_PHY_ADDR_SHIFT) |
IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC |
IXGBE_MSCA_MDI_COMMAND;
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
/* Check every 10 usec to see if the access completed.
* The MDI Command bit will clear when the operation is
* complete
*/
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if (!(command & IXGBE_MSCA_MDI_COMMAND))
break;
}
if (command & IXGBE_MSCA_MDI_COMMAND)
return IXGBE_ERR_PHY;
/* Read operation is complete. Get the data from MSRWD */
data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
*phy_data = (u16)data;
return 0;
}
int __rte_experimental
rte_pmd_ixgbe_mdio_unlocked_write(uint16_t port, uint32_t reg_addr,
uint32_t dev_type, uint16_t phy_data)
{
struct ixgbe_hw *hw;
u32 i, command;
struct rte_eth_dev *dev;
RTE_ETH_VALID_PORTID_OR_ERR_RET(port, -ENODEV);
dev = &rte_eth_devices[port];
if (!is_ixgbe_supported(dev))
return -ENOTSUP;
hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!hw)
return -ENOTSUP;
/* Put the data in the MDI single read and write data register*/
IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
/* Setup and write the write command */
command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
(dev_type << IXGBE_MSCA_PHY_ADDR_SHIFT) |
IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
IXGBE_MSCA_MDI_COMMAND;
IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
/* Check every 10 usec to see if the access completed.
* The MDI Command bit will clear when the operation is
* complete
*/
for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
usec_delay(10);
command = IXGBE_READ_REG(hw, IXGBE_MSCA);
if (!(command & IXGBE_MSCA_MDI_COMMAND))
break;
}
if (command & IXGBE_MSCA_MDI_COMMAND) {
ERROR_REPORT1(IXGBE_ERROR_POLLING,
"PHY write cmd didn't complete\n");
return IXGBE_ERR_PHY;
}
return 0;
}