You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.6 KiB
82 lines
2.6 KiB
From 9d4c65d0e7ebfe20bd24e65d52b1df56e90d498e Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
|
Date: Tue, 10 Apr 2018 15:27:51 +0100
|
|
Subject: [PATCH 271/454] 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: Dave Stevenson <dave.stevenson@raspberrypi.org>
|
|
---
|
|
drivers/net/usb/lan78xx.c | 22 ++++++++++++++++++++++
|
|
1 file changed, 22 insertions(+)
|
|
|
|
--- a/drivers/net/usb/lan78xx.c
|
|
+++ b/drivers/net/usb/lan78xx.c
|
|
@@ -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
|
|
|
|
@@ -2279,6 +2280,11 @@ static int lan78xx_set_features(struct n
|
|
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
|
|
@@ -2892,6 +2898,9 @@ static int lan78xx_bind(struct lan78xx_n
|
|
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;
|
|
|
|
@@ -2972,6 +2981,16 @@ static void lan78xx_rx_csum_offload(stru
|
|
}
|
|
}
|
|
|
|
+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;
|
|
@@ -3036,6 +3055,8 @@ static int lan78xx_rx(struct lan78xx_net
|
|
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);
|
|
@@ -3054,6 +3075,7 @@ static int lan78xx_rx(struct lan78xx_net
|
|
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);
|
|
|