e1000: add vlan offload support
Signed-off-by: Intel
This commit is contained in:
parent
8cebf9e58f
commit
7da9ffee83
@ -49,8 +49,8 @@
|
||||
#define E1000_RXD_ERR_CKSUM_BIT 29
|
||||
#define E1000_RXD_ERR_CKSUM_MSK 3
|
||||
#define E1000_ADVTXD_MACLEN_SHIFT 9 /* Bit shift for l2_len */
|
||||
|
||||
#define E1000_VFTA_SIZE 128
|
||||
#define E1000_CTRL_EXT_EXTEND_VLAN (1<<26) /* EXTENDED VLAN */
|
||||
#define IGB_VFTA_SIZE 128
|
||||
|
||||
/* structure for interrupt relative data */
|
||||
struct e1000_interrupt {
|
||||
@ -59,7 +59,7 @@ struct e1000_interrupt {
|
||||
|
||||
/* local vfta copy */
|
||||
struct e1000_vfta {
|
||||
uint32_t vfta[E1000_VFTA_SIZE];
|
||||
uint32_t vfta[IGB_VFTA_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -85,11 +85,19 @@ static void igb_hw_control_acquire(struct e1000_hw *hw);
|
||||
static void igb_hw_control_release(struct e1000_hw *hw);
|
||||
static void igb_init_manageability(struct e1000_hw *hw);
|
||||
static void igb_release_manageability(struct e1000_hw *hw);
|
||||
static void igb_vlan_hw_support_enable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_support_disable(struct rte_eth_dev *dev);
|
||||
static void eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
|
||||
uint16_t vlan_id,
|
||||
int on);
|
||||
|
||||
static int eth_igb_vlan_filter_set(struct rte_eth_dev *dev,
|
||||
uint16_t vlan_id, int on);
|
||||
static void eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid_id);
|
||||
static void eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask);
|
||||
|
||||
static void igb_vlan_hw_filter_enable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_filter_disable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_strip_enable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_strip_disable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_extend_enable(struct rte_eth_dev *dev);
|
||||
static void igb_vlan_hw_extend_disable(struct rte_eth_dev *dev);
|
||||
|
||||
static int eth_igb_led_on(struct rte_eth_dev *dev);
|
||||
static int eth_igb_led_off(struct rte_eth_dev *dev);
|
||||
|
||||
@ -166,6 +174,8 @@ static struct eth_dev_ops eth_igb_ops = {
|
||||
.stats_reset = eth_igb_stats_reset,
|
||||
.dev_infos_get = eth_igb_infos_get,
|
||||
.vlan_filter_set = eth_igb_vlan_filter_set,
|
||||
.vlan_tpid_set = eth_igb_vlan_tpid_set,
|
||||
.vlan_offload_set = eth_igb_vlan_offload_set,
|
||||
.rx_queue_setup = eth_igb_rx_queue_setup,
|
||||
.tx_queue_setup = eth_igb_tx_queue_setup,
|
||||
.dev_led_on = eth_igb_led_on,
|
||||
@ -576,13 +586,11 @@ eth_igb_start(struct rte_eth_dev *dev)
|
||||
e1000_clear_hw_cntrs_base_generic(hw);
|
||||
|
||||
/*
|
||||
* If VLAN filtering is enabled, set up VLAN tag offload and filtering
|
||||
* and restore the VFTA.
|
||||
* VLAN Offload Settings
|
||||
*/
|
||||
if (dev->data->dev_conf.rxmode.hw_vlan_filter)
|
||||
igb_vlan_hw_support_enable(dev);
|
||||
else
|
||||
igb_vlan_hw_support_disable(dev);
|
||||
mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | \
|
||||
ETH_VLAN_EXTEND_MASK;
|
||||
eth_igb_vlan_offload_set(dev, mask);
|
||||
|
||||
/*
|
||||
* Configure the Interrupt Moderation register (EITR) with the maximum
|
||||
@ -1258,7 +1266,7 @@ eth_igb_allmulticast_disable(struct rte_eth_dev *dev)
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, rctl);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
@ -1281,10 +1289,37 @@ eth_igb_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on)
|
||||
|
||||
/* update local VFTA copy */
|
||||
shadow_vfta->vfta[vid_idx] = vfta;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_support_enable(struct rte_eth_dev *dev)
|
||||
eth_igb_vlan_tpid_set(struct rte_eth_dev *dev, uint16_t tpid)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg = ETHER_TYPE_VLAN ;
|
||||
|
||||
reg |= (tpid << 16);
|
||||
E1000_WRITE_REG(hw, E1000_VET, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_filter_disable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg;
|
||||
|
||||
/* Filter Table Disable */
|
||||
reg = E1000_READ_REG(hw, E1000_RCTL);
|
||||
reg &= ~E1000_RCTL_CFIEN;
|
||||
reg &= ~E1000_RCTL_VFE;
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_filter_enable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
@ -1293,38 +1328,102 @@ igb_vlan_hw_support_enable(struct rte_eth_dev *dev)
|
||||
uint32_t reg;
|
||||
int i;
|
||||
|
||||
/* VLAN Mode Enable */
|
||||
reg = E1000_READ_REG(hw, E1000_CTRL);
|
||||
reg |= E1000_CTRL_VME;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, reg);
|
||||
|
||||
/* Filter Table Enable */
|
||||
/* Filter Table Enable, CFI not used for packet acceptance */
|
||||
reg = E1000_READ_REG(hw, E1000_RCTL);
|
||||
reg &= ~E1000_RCTL_CFIEN;
|
||||
reg |= E1000_RCTL_VFE;
|
||||
E1000_WRITE_REG(hw, E1000_RCTL, reg);
|
||||
|
||||
/* Update maximum frame size */
|
||||
reg = E1000_READ_REG(hw, E1000_RLPML);
|
||||
reg += VLAN_TAG_SIZE;
|
||||
E1000_WRITE_REG(hw, E1000_RLPML, reg);
|
||||
|
||||
/* restore VFTA table */
|
||||
for (i = 0; i < E1000_VFTA_SIZE; i++)
|
||||
for (i = 0; i < IGB_VFTA_SIZE; i++)
|
||||
E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, i, shadow_vfta->vfta[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_support_disable(struct rte_eth_dev *dev)
|
||||
igb_vlan_hw_strip_disable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg;
|
||||
|
||||
/* VLAN Mode disable */
|
||||
/* VLAN Mode Disable */
|
||||
reg = E1000_READ_REG(hw, E1000_CTRL);
|
||||
reg &= ~E1000_CTRL_VME;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, reg);
|
||||
|
||||
/* Update maximum frame size */
|
||||
E1000_WRITE_REG(hw, E1000_RLPML,
|
||||
dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_strip_enable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg;
|
||||
|
||||
/* VLAN Mode Enable */
|
||||
reg = E1000_READ_REG(hw, E1000_CTRL);
|
||||
reg |= E1000_CTRL_VME;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL, reg);
|
||||
|
||||
/* Update maximum frame size */
|
||||
E1000_WRITE_REG(hw, E1000_RLPML,
|
||||
dev->data->dev_conf.rxmode.max_rx_pkt_len);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_extend_disable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg;
|
||||
|
||||
/* CTRL_EXT: Extended VLAN */
|
||||
reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
|
||||
reg &= ~E1000_CTRL_EXT_EXTEND_VLAN;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
igb_vlan_hw_extend_enable(struct rte_eth_dev *dev)
|
||||
{
|
||||
struct e1000_hw *hw =
|
||||
E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
|
||||
uint32_t reg;
|
||||
|
||||
/* CTRL_EXT: Extended VLAN */
|
||||
reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
|
||||
reg |= E1000_CTRL_EXT_EXTEND_VLAN;
|
||||
E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
eth_igb_vlan_offload_set(struct rte_eth_dev *dev, int mask)
|
||||
{
|
||||
if(mask & ETH_VLAN_STRIP_MASK){
|
||||
if (dev->data->dev_conf.rxmode.hw_vlan_strip)
|
||||
igb_vlan_hw_strip_enable(dev);
|
||||
else
|
||||
igb_vlan_hw_strip_disable(dev);
|
||||
}
|
||||
|
||||
if(mask & ETH_VLAN_FILTER_MASK){
|
||||
if (dev->data->dev_conf.rxmode.hw_vlan_filter)
|
||||
igb_vlan_hw_filter_enable(dev);
|
||||
else
|
||||
igb_vlan_hw_filter_disable(dev);
|
||||
}
|
||||
|
||||
if(mask & ETH_VLAN_EXTEND_MASK){
|
||||
if (dev->data->dev_conf.rxmode.hw_vlan_extend)
|
||||
igb_vlan_hw_extend_enable(dev);
|
||||
else
|
||||
igb_vlan_hw_extend_disable(dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1691,7 +1691,8 @@ eth_igb_rx_init(struct rte_eth_dev *dev)
|
||||
E1000_SRRCTL_BSIZEPKT_MASK) <<
|
||||
E1000_SRRCTL_BSIZEPKT_SHIFT);
|
||||
|
||||
if (dev->data->dev_conf.rxmode.max_rx_pkt_len > buf_size){
|
||||
if (dev->data->dev_conf.rxmode.max_rx_pkt_len + VLAN_TAG_SIZE
|
||||
> buf_size){
|
||||
dev->rx_pkt_burst = eth_igb_recv_scattered_pkts;
|
||||
dev->data->scattered_rx = 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user