aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ramips
diff options
context:
space:
mode:
authorJohn Crispin <blogic@openwrt.org>2014-11-19 09:19:43 +0000
committerJohn Crispin <blogic@openwrt.org>2014-11-19 09:19:43 +0000
commit2825bdda9f7bb19958953066aba7ab4912f0d0e8 (patch)
treea783c25ef91cadc95160568826676ebdc497de0a /target/linux/ramips
parentb598129396cdd929f1c63a8fbdfb00f8b3618460 (diff)
downloadupstream-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.c54
-rw-r--r--target/linux/ramips/files/drivers/net/ethernet/ralink/ralink_soc_eth.h1
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[];