Commit 3a3fab31 authored by Dave Stevenson's avatar Dave Stevenson Committed by Phil Elwell
Browse files

net: lan78xx: Add support for VLAN tag stripping.



The chip supports stripping the VLAN tag and reporting it
in metadata. Implement this as it also appears to solve the
issues observed in checksum computation.

See #2458.

Signed-off-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.org>
parent 7a6e7a4c
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@
#define DEFAULT_RX_CSUM_ENABLE		(true)
#define DEFAULT_TSO_CSUM_ENABLE		(true)
#define DEFAULT_VLAN_FILTER_ENABLE	(true)
#define DEFAULT_VLAN_RX_OFFLOAD		(true)
#define TX_OVERHEAD			(8)
#define RXW_PADDING			2

@@ -2295,6 +2296,11 @@ static int lan78xx_set_features(struct net_device *netdev,
		pdata->rfe_ctl &= ~(RFE_CTL_ICMP_COE_ | RFE_CTL_IGMP_COE_);
	}

	if (features & NETIF_F_HW_VLAN_CTAG_RX)
		pdata->rfe_ctl |= RFE_CTL_VLAN_STRIP_;
	else
		pdata->rfe_ctl &= ~RFE_CTL_VLAN_STRIP_;

	if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
		pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_;
	else
@@ -2909,6 +2915,9 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
	if (DEFAULT_TSO_CSUM_ENABLE)
		dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG;

	if (DEFAULT_VLAN_RX_OFFLOAD)
		dev->net->features |= NETIF_F_HW_VLAN_CTAG_RX;

	if (DEFAULT_VLAN_FILTER_ENABLE)
		dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER;

@@ -2989,6 +2998,16 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
	}
}

static void lan78xx_rx_vlan_offload(struct lan78xx_net *dev,
				    struct sk_buff *skb,
				    u32 rx_cmd_a, u32 rx_cmd_b)
{
	if ((dev->net->features & NETIF_F_HW_VLAN_CTAG_RX) &&
	    (rx_cmd_a & RX_CMD_A_FVTG_))
		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
				       (rx_cmd_b & 0xffff));
}

static void lan78xx_skb_return(struct lan78xx_net *dev, struct sk_buff *skb)
{
	int		status;
@@ -3053,6 +3072,8 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb)
			if (skb->len == size) {
				lan78xx_rx_csum_offload(dev, skb,
							rx_cmd_a, rx_cmd_b);
				lan78xx_rx_vlan_offload(dev, skb,
							rx_cmd_a, rx_cmd_b);

				skb_trim(skb, skb->len - 4); /* remove fcs */
				skb->truesize = size + sizeof(struct sk_buff);
@@ -3071,6 +3092,7 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb)
			skb_set_tail_pointer(skb2, size);

			lan78xx_rx_csum_offload(dev, skb2, rx_cmd_a, rx_cmd_b);
			lan78xx_rx_vlan_offload(dev, skb2, rx_cmd_a, rx_cmd_b);

			skb_trim(skb2, skb2->len - 4); /* remove fcs */
			skb2->truesize = size + sizeof(struct sk_buff);