mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-15 21:26:40 +07:00
ice: Fix transmit for all software offloaded VLANs
Currently the driver does not recognize when there is an 802.1AD VLAN tag right after the dmac/smac (outermost VLAN tag). If any DCB map is applied and/or DCB is enabled this is causing the hardware to insert a VLAN 0 tag after the 802.1AD VLAN tag that is already in the packet. Fix this by preventing VLAN tag 0 from being added when any VLAN is already present after dmac/smac (software offloaded) or skb (hardware offloaded). Signed-off-by: Brett Creeley <brett.creeley@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
c1636a6e8a
commit
2bb19d6e07
@ -791,39 +791,31 @@ void ice_update_dcb_stats(struct ice_pf *pf)
|
||||
* ice_tx_prepare_vlan_flags_dcb - prepare VLAN tagging for DCB
|
||||
* @tx_ring: ring to send buffer on
|
||||
* @first: pointer to struct ice_tx_buf
|
||||
*
|
||||
* This should not be called if the outer VLAN is software offloaded as the VLAN
|
||||
* tag will already be configured with the correct ID and priority bits
|
||||
*/
|
||||
int
|
||||
void
|
||||
ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
|
||||
struct ice_tx_buf *first)
|
||||
{
|
||||
struct sk_buff *skb = first->skb;
|
||||
|
||||
if (!test_bit(ICE_FLAG_DCB_ENA, tx_ring->vsi->back->flags))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* Insert 802.1p priority into VLAN header */
|
||||
if ((first->tx_flags & (ICE_TX_FLAGS_HW_VLAN | ICE_TX_FLAGS_SW_VLAN)) ||
|
||||
if ((first->tx_flags & ICE_TX_FLAGS_HW_VLAN) ||
|
||||
skb->priority != TC_PRIO_CONTROL) {
|
||||
first->tx_flags &= ~ICE_TX_FLAGS_VLAN_PR_M;
|
||||
/* Mask the lower 3 bits to set the 802.1p priority */
|
||||
first->tx_flags |= (skb->priority & 0x7) <<
|
||||
ICE_TX_FLAGS_VLAN_PR_S;
|
||||
if (first->tx_flags & ICE_TX_FLAGS_SW_VLAN) {
|
||||
struct vlan_ethhdr *vhdr;
|
||||
int rc;
|
||||
|
||||
rc = skb_cow_head(skb, 0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
vhdr = (struct vlan_ethhdr *)skb->data;
|
||||
vhdr->h_vlan_TCI = htons(first->tx_flags >>
|
||||
ICE_TX_FLAGS_VLAN_S);
|
||||
} else {
|
||||
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
|
||||
}
|
||||
/* if this is not already set it means a VLAN 0 + priority needs
|
||||
* to be offloaded
|
||||
*/
|
||||
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -27,7 +27,7 @@ void ice_pf_dcb_recfg(struct ice_pf *pf);
|
||||
void ice_vsi_cfg_dcb_rings(struct ice_vsi *vsi);
|
||||
int ice_init_pf_dcb(struct ice_pf *pf, bool locked);
|
||||
void ice_update_dcb_stats(struct ice_pf *pf);
|
||||
int
|
||||
void
|
||||
ice_tx_prepare_vlan_flags_dcb(struct ice_ring *tx_ring,
|
||||
struct ice_tx_buf *first);
|
||||
void
|
||||
|
@ -2053,49 +2053,25 @@ int ice_tx_csum(struct ice_tx_buf *first, struct ice_tx_offload_params *off)
|
||||
*
|
||||
* Checks the skb and set up correspondingly several generic transmit flags
|
||||
* related to VLAN tagging for the HW, such as VLAN, DCB, etc.
|
||||
*
|
||||
* Returns error code indicate the frame should be dropped upon error and the
|
||||
* otherwise returns 0 to indicate the flags has been set properly.
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
ice_tx_prepare_vlan_flags(struct ice_ring *tx_ring, struct ice_tx_buf *first)
|
||||
{
|
||||
struct sk_buff *skb = first->skb;
|
||||
__be16 protocol = skb->protocol;
|
||||
|
||||
if (protocol == htons(ETH_P_8021Q) &&
|
||||
!(tx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_TX)) {
|
||||
/* when HW VLAN acceleration is turned off by the user the
|
||||
* stack sets the protocol to 8021q so that the driver
|
||||
* can take any steps required to support the SW only
|
||||
* VLAN handling. In our case the driver doesn't need
|
||||
* to take any further steps so just set the protocol
|
||||
* to the encapsulated ethertype.
|
||||
*/
|
||||
skb->protocol = vlan_get_protocol(skb);
|
||||
return 0;
|
||||
}
|
||||
/* nothing left to do, software offloaded VLAN */
|
||||
if (!skb_vlan_tag_present(skb) && eth_type_vlan(skb->protocol))
|
||||
return;
|
||||
|
||||
/* if we have a HW VLAN tag being added, default to the HW one */
|
||||
/* currently, we always assume 802.1Q for VLAN insertion as VLAN
|
||||
* insertion for 802.1AD is not supported
|
||||
*/
|
||||
if (skb_vlan_tag_present(skb)) {
|
||||
first->tx_flags |= skb_vlan_tag_get(skb) << ICE_TX_FLAGS_VLAN_S;
|
||||
first->tx_flags |= ICE_TX_FLAGS_HW_VLAN;
|
||||
} else if (protocol == htons(ETH_P_8021Q)) {
|
||||
struct vlan_hdr *vhdr, _vhdr;
|
||||
|
||||
/* for SW VLAN, check the next protocol and store the tag */
|
||||
vhdr = (struct vlan_hdr *)skb_header_pointer(skb, ETH_HLEN,
|
||||
sizeof(_vhdr),
|
||||
&_vhdr);
|
||||
if (!vhdr)
|
||||
return -EINVAL;
|
||||
|
||||
first->tx_flags |= ntohs(vhdr->h_vlan_TCI) <<
|
||||
ICE_TX_FLAGS_VLAN_S;
|
||||
first->tx_flags |= ICE_TX_FLAGS_SW_VLAN;
|
||||
}
|
||||
|
||||
return ice_tx_prepare_vlan_flags_dcb(tx_ring, first);
|
||||
ice_tx_prepare_vlan_flags_dcb(tx_ring, first);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2403,8 +2379,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)
|
||||
first->tx_flags = 0;
|
||||
|
||||
/* prepare the VLAN tagging flags for Tx */
|
||||
if (ice_tx_prepare_vlan_flags(tx_ring, first))
|
||||
goto out_drop;
|
||||
ice_tx_prepare_vlan_flags(tx_ring, first);
|
||||
|
||||
/* set up TSO offload */
|
||||
tso = ice_tso(first, &offload);
|
||||
|
Loading…
Reference in New Issue
Block a user