diff options
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/common.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/hwif.h | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 58 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c | 5 |
4 files changed, 40 insertions, 27 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 8403a3e17211..dff7a12047a2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -661,7 +661,6 @@ struct mac_device_info { u32 vlan_filter[32]; bool vlan_fail_q_en; u8 vlan_fail_q; - bool hw_vlan_en; bool reverse_sgmii_enable; /* This spinlock protects read-modify-write of the interrupt diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 45111ec4902f..6996fe2e1336 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -632,7 +632,8 @@ struct stmmac_vlan_ops { bool is_svlan); void (*rx_hw_vlan)(struct mac_device_info *hw, struct dma_desc *rx_desc, struct sk_buff *skb); - void (*set_hw_vlan_mode)(struct mac_device_info *hw, bool tx_stag); + void (*set_hw_vlan_mode)(struct mac_device_info *hw, bool rx_strip, + bool tx_stag); int (*add_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw, __be16 proto, u16 vid); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index ae2dea6b3d3c..47de06bbde2f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3893,6 +3893,8 @@ static int stmmac_hw_setup(struct net_device *dev) phylink_rx_clk_stop_block(priv->phylink); stmmac_set_hw_vlan_mode(priv, priv->hw, + dev->features & (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX), dev->features & NETIF_F_HW_VLAN_STAG_TX); phylink_rx_clk_stop_unblock(priv->phylink); @@ -5158,22 +5160,43 @@ static int stmmac_get_rx_status(struct stmmac_priv *priv, struct dma_desc *p) return ret | discard_frame; } -static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) +/** + * stmmac_get_rx_vlan - Extract VLAN ID from the frame + * @priv: driver private structure + * @p : descriptor pointer + * @skb : the socket buffer + * Description : + * This function will either read the VLAN ID and TCI from the DMA-descriptor + * (if it's supported the VLAN stripping has been enabled) or just perform + * the VLAN header stripping directly from the payload. + */ +static void stmmac_get_rx_vlan(struct stmmac_priv *priv, struct dma_desc *p, + struct sk_buff *skb) { +#ifdef STMMAC_VLAN_TAG_USED struct vlan_ethhdr *veth = skb_vlan_eth_hdr(skb); - __be16 vlan_proto = veth->h_vlan_proto; + __be16 vlan_proto; u16 vlanid; + int ret; + + /* MAC level stripping */ + ret = stmmac_rx_hw_vlan(priv, priv->hw, p, skb); + if (!ret) + return; + /* Driver level stripping */ + vlan_proto = veth->h_vlan_proto; if ((vlan_proto == htons(ETH_P_8021Q) && - dev->features & NETIF_F_HW_VLAN_CTAG_RX) || + priv->dev->features & NETIF_F_HW_VLAN_CTAG_RX) || (vlan_proto == htons(ETH_P_8021AD) && - dev->features & NETIF_F_HW_VLAN_STAG_RX)) { + priv->dev->features & NETIF_F_HW_VLAN_STAG_RX)) { /* pop the vlan tag */ vlanid = ntohs(veth->h_vlan_TCI); memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2); skb_pull(skb, VLAN_HLEN); __vlan_hwaccel_put_tag(skb, vlan_proto, vlanid); } +#endif } /** @@ -5639,12 +5662,9 @@ static void stmmac_dispatch_skb_zc(struct stmmac_priv *priv, u32 queue, } stmmac_get_rx_hwtstamp(priv, p, np, skb); - if (priv->hw->hw_vlan_en) - /* MAC level stripping. */ - stmmac_rx_hw_vlan(priv, priv->hw, p, skb); - else - /* Driver level stripping. */ - stmmac_rx_vlan(priv->dev, skb); + + stmmac_get_rx_vlan(priv, p, skb); + skb->protocol = eth_type_trans(skb, priv->dev); stmmac_get_rx_csum(priv, status, skb); @@ -6133,12 +6153,7 @@ drain_data: stmmac_get_rx_hwtstamp(priv, p, np, skb); - if (priv->hw->hw_vlan_en) - /* MAC level stripping. */ - stmmac_rx_hw_vlan(priv, priv->hw, p, skb); - else - /* Driver level stripping. */ - stmmac_rx_vlan(priv->dev, skb); + stmmac_get_rx_vlan(priv, p, skb); skb->protocol = eth_type_trans(skb, priv->dev); @@ -6502,11 +6517,10 @@ static int stmmac_set_features(struct net_device *netdev, features & NETIF_F_RXHASH, priv->plat->rx_queues_to_use); - if (netdev->hw_features & NETIF_F_HW_VLAN_CTAG_RX) - priv->hw->hw_vlan_en = !!(features & NETIF_F_HW_VLAN_CTAG_RX); - phylink_rx_clk_stop_block(priv->phylink); stmmac_set_hw_vlan_mode(priv, priv->hw, + features & (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX), features & NETIF_F_HW_VLAN_STAG_TX); phylink_rx_clk_stop_unblock(priv->phylink); @@ -8753,10 +8767,8 @@ static int __stmmac_dvr_probe(struct device *device, #ifdef STMMAC_VLAN_TAG_USED /* Both mac100 and gmac support receive VLAN tag detection */ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; - if (dwmac_is_xmac(priv->plat->core_type)) { - ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; - priv->hw->hw_vlan_en = true; - } + ndev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX; + if (priv->dma_cap.vlhash) { ndev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; ndev->features |= NETIF_F_HW_VLAN_STAG_FILTER; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c index 77fe0ea31c33..bb0521978453 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -239,14 +239,15 @@ static void vlan_rx_hw(struct mac_device_info *hw, } } -static void vlan_set_hw_mode(struct mac_device_info *hw, bool tx_stag) +static void vlan_set_hw_mode(struct mac_device_info *hw, bool rx_strip, + bool tx_stag) { void __iomem *ioaddr = hw->pcsr; u32 value = readl(ioaddr + VLAN_TAG); value &= ~VLAN_TAG_CTRL_EVLS_MASK; - if (hw->hw_vlan_en) + if (rx_strip) /* Always strip VLAN on Receive */ value |= VLAN_TAG_STRIP_ALL; else |
