diff options
author | John Crispin <blogic@openwrt.org> | 2014-11-19 09:19:43 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2014-11-19 09:19:43 +0000 |
commit | 2825bdda9f7bb19958953066aba7ab4912f0d0e8 (patch) | |
tree | a783c25ef91cadc95160568826676ebdc497de0a /target/linux/ramips | |
parent | b598129396cdd929f1c63a8fbdfb00f8b3618460 (diff) | |
download | upstream-2825bdda9f7bb19958953066aba7ab4912f0d0e8.tar.gz upstream-2825bdda9f7bb19958953066aba7ab4912f0d0e8.tar.bz2 upstream-2825bdda9f7bb19958953066aba7ab4912f0d0e8.zip |
ralink: improve tx vlan offload
hardware tx vlan offload only support max 16 vids
now use add/delete vlan interface to update vlan id table
when duplicate vlan id index detect.
disable hardware tx vlan offload support.
Signed-off-by: michael lee <igvtee@gmail.com>
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@43301 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/ramips')
-rw-r--r-- | target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c | 54 | ||||
-rw-r--r-- | target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h | 1 |
2 files changed, 55 insertions, 0 deletions
diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c index f09751040b..c62fb8f56d 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.c @@ -418,6 +418,54 @@ static struct rtnl_link_stats64 *fe_get_stats64(struct net_device *dev, return storage; } +static int fe_vlan_rx_add_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + u32 vlan_cfg; + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features | NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + if (test_bit(idx, &priv->vlan_map)) { + netdev_warn(dev, "disable tx vlan offload\n"); + dev->wanted_features &= ~NETIF_F_HW_VLAN_CTAG_TX; + netdev_update_features(dev); + } else { + vlan_cfg = fe_r32(fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + if (idx & 0x1) { + vlan_cfg &= 0xffff; + vlan_cfg |= (vid << 16); + } else { + vlan_cfg &= 0xffff0000; + vlan_cfg |= vid; + } + fe_w32(vlan_cfg, fe_reg_table[FE_REG_FE_DMA_VID_BASE] + + ((idx >> 1) << 2)); + set_bit(idx, &priv->vlan_map); + } + + return 0; +} + +static int fe_vlan_rx_kill_vid(struct net_device *dev, + __be16 proto, u16 vid) +{ + struct fe_priv *priv = netdev_priv(dev); + u32 idx = (vid & 0xf); + + if (!((fe_reg_table[FE_REG_FE_DMA_VID_BASE]) && + (dev->features | NETIF_F_HW_VLAN_CTAG_TX))) + return 0; + + clear_bit(idx, &priv->vlan_map); + + return 0; +} + static int fe_tx_map_dma(struct sk_buff *skb, struct net_device *dev, int idx) { @@ -1182,6 +1230,8 @@ static const struct net_device_ops fe_netdev_ops = { .ndo_change_mtu = fe_change_mtu, .ndo_tx_timeout = fe_tx_timeout, .ndo_get_stats64 = fe_get_stats64, + .ndo_vlan_rx_add_vid = fe_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = fe_vlan_rx_kill_vid, }; static int fe_probe(struct platform_device *pdev) @@ -1237,6 +1287,10 @@ static int fe_probe(struct platform_device *pdev) ~(NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX); netdev->features |= netdev->hw_features; + /* fake rx vlan filter func. to support tx vlan offload func */ + if (fe_reg_table[FE_REG_FE_DMA_VID_BASE]) + netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; + priv = netdev_priv(netdev); spin_lock_init(&priv->page_lock); if (fe_reg_table[FE_REG_FE_COUNTER_BASE]) { diff --git a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h index 67d5ce65cf..8245330fbc 100644 --- a/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h +++ b/target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h @@ -432,6 +432,7 @@ struct fe_priv int link[8]; struct fe_hw_stats *hw_stats; + unsigned long vlan_map; }; extern const struct of_device_id of_fe_match[]; |