Commit ec21ecf0 authored by Dave Stevenson's avatar Dave Stevenson Committed by David S. Miller

net: lan78xx: Add support for VLAN tag stripping.

The chip supports stripping the VLAN tag and reporting it
in metadata.
Complete the support for this.
Signed-off-by: default avatarDave Stevenson <dave.stevenson@raspberrypi.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4a27327b
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
#define DEFAULT_RX_CSUM_ENABLE (true) #define DEFAULT_RX_CSUM_ENABLE (true)
#define DEFAULT_TSO_CSUM_ENABLE (true) #define DEFAULT_TSO_CSUM_ENABLE (true)
#define DEFAULT_VLAN_FILTER_ENABLE (true) #define DEFAULT_VLAN_FILTER_ENABLE (true)
#define DEFAULT_VLAN_RX_OFFLOAD (true)
#define TX_OVERHEAD (8) #define TX_OVERHEAD (8)
#define RXW_PADDING 2 #define RXW_PADDING 2
...@@ -2363,6 +2364,11 @@ static int lan78xx_set_features(struct net_device *netdev, ...@@ -2363,6 +2364,11 @@ static int lan78xx_set_features(struct net_device *netdev,
pdata->rfe_ctl &= ~(RFE_CTL_ICMP_COE_ | RFE_CTL_IGMP_COE_); 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) if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_; pdata->rfe_ctl |= RFE_CTL_VLAN_FILTER_;
else else
...@@ -2976,6 +2982,9 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) ...@@ -2976,6 +2982,9 @@ static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf)
if (DEFAULT_TSO_CSUM_ENABLE) if (DEFAULT_TSO_CSUM_ENABLE)
dev->net->features |= NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_SG; 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) if (DEFAULT_VLAN_FILTER_ENABLE)
dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER; dev->net->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
...@@ -3052,6 +3061,16 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev, ...@@ -3052,6 +3061,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) static void lan78xx_skb_return(struct lan78xx_net *dev, struct sk_buff *skb)
{ {
int status; int status;
...@@ -3116,6 +3135,8 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb) ...@@ -3116,6 +3135,8 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb)
if (skb->len == size) { if (skb->len == size) {
lan78xx_rx_csum_offload(dev, skb, lan78xx_rx_csum_offload(dev, skb,
rx_cmd_a, rx_cmd_b); 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_trim(skb, skb->len - 4); /* remove fcs */
skb->truesize = size + sizeof(struct sk_buff); skb->truesize = size + sizeof(struct sk_buff);
...@@ -3134,6 +3155,7 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb) ...@@ -3134,6 +3155,7 @@ static int lan78xx_rx(struct lan78xx_net *dev, struct sk_buff *skb)
skb_set_tail_pointer(skb2, size); skb_set_tail_pointer(skb2, size);
lan78xx_rx_csum_offload(dev, skb2, rx_cmd_a, rx_cmd_b); 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 */ skb_trim(skb2, skb2->len - 4); /* remove fcs */
skb2->truesize = size + sizeof(struct sk_buff); skb2->truesize = size + sizeof(struct sk_buff);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment