diff options
author | John Crispin <john@phrozen.org> | 2018-03-23 13:42:56 +0100 |
---|---|---|
committer | Felix Fietkau <nbd@nbd.name> | 2018-04-06 19:37:53 +0200 |
commit | 424a9ae128bd2045cd4bfd6e3229f2529d150a25 (patch) | |
tree | 2d82652a341a08c3edb660893c20315d5cafc41e /target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c | |
parent | dea9922acd290b37a784d354892a44684a8fb696 (diff) | |
download | upstream-424a9ae128bd2045cd4bfd6e3229f2529d150a25.tar.gz upstream-424a9ae128bd2045cd4bfd6e3229f2529d150a25.tar.bz2 upstream-424a9ae128bd2045cd4bfd6e3229f2529d150a25.zip |
ramips: implement hardware NAT offload for MT7621
Supports IPv4 flow offloading on MT7621 for Routing, SNAT and DNAT
Supported are regular ethernet->ethernet connections, including one
802.1q VLAN and/or PPPoE encapsulation
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Diffstat (limited to 'target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c')
-rw-r--r-- | target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c index 03da3bbe20..0fce0efc94 100644 --- a/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c +++ b/target/linux/ramips/files-4.14/drivers/net/ethernet/mtk/mtk_eth_soc.c @@ -30,6 +30,8 @@ #include <linux/tcp.h> #include <linux/io.h> #include <linux/bug.h> +#include <linux/netfilter.h> +#include <net/netfilter/nf_flow_table.h> #include <asm/mach-ralink/ralink_regs.h> @@ -110,6 +112,18 @@ u32 fe_reg_r32(enum fe_reg reg) return fe_r32(fe_reg_table[reg]); } +void fe_m32(struct fe_priv *eth, u32 clear, u32 set, unsigned reg) +{ + u32 val; + + spin_lock(ð->page_lock); + val = __raw_readl(fe_base + reg); + val &= ~clear; + val |= set; + __raw_writel(val, fe_base + reg); + spin_unlock(ð->page_lock); +} + void fe_reset(u32 reset_bits) { u32 t; @@ -865,10 +879,14 @@ static int fe_poll_rx(struct napi_struct *napi, int budget, skb_checksum_none_assert(skb); skb->protocol = eth_type_trans(skb, netdev); - stats->rx_packets++; - stats->rx_bytes += pktlen; + if (mtk_offload_check_rx(priv, skb, trxd.rxd4) == 0) { + stats->rx_packets++; + stats->rx_bytes += pktlen; - napi_gro_receive(napi, skb); + napi_gro_receive(napi, skb); + } else { + dev_kfree_skb(skb); + } ring->rx_data[idx] = new_data; rxd->rxd1 = (unsigned int)dma_addr; @@ -1207,6 +1225,9 @@ static int fe_open(struct net_device *dev) napi_enable(&priv->rx_napi); fe_int_enable(priv->soc->tx_int | priv->soc->rx_int); netif_start_queue(dev); +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + mtk_ppe_probe(priv); +#endif return 0; } @@ -1243,6 +1264,10 @@ static int fe_stop(struct net_device *dev) fe_free_dma(priv); +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + mtk_ppe_remove(priv); +#endif + return 0; } @@ -1390,6 +1415,23 @@ static int fe_change_mtu(struct net_device *dev, int new_mtu) return fe_open(dev); } +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD +static int +fe_flow_offload(enum flow_offload_type type, struct flow_offload *flow, + struct flow_offload_hw_path *src, + struct flow_offload_hw_path *dest) +{ + struct fe_priv *priv; + + if (src->dev != dest->dev) + return -EINVAL; + + priv = netdev_priv(src->dev); + + return mtk_flow_offload(priv, type, flow, src, dest); +} +#endif + static const struct net_device_ops fe_netdev_ops = { .ndo_init = fe_init, .ndo_uninit = fe_uninit, @@ -1407,6 +1449,9 @@ static const struct net_device_ops fe_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = fe_poll_controller, #endif +#ifdef CONFIG_NET_MEDIATEK_OFFLOAD + .ndo_flow_offload = fe_flow_offload, +#endif }; static void fe_reset_pending(struct fe_priv *priv) |