mirror of
https://github.com/hanwckf/immortalwrt-mt798x.git
synced 2025-01-10 03:09:08 +08:00
mediatek: rewrite flow offload code
The code is now much cleaner and works better than the old code. Preparation for submitting it upstream (though with a different API) Also add back MT7621 support and fix flow table coherence issues on MT7622 Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
ba9b6702aa
commit
b59d5c8f0e
@ -18,14 +18,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
#include "mtk_eth_soc.h"
|
#include "mtk_eth_soc.h"
|
||||||
|
|
||||||
@@ -1240,12 +1241,14 @@ static int mtk_poll_rx(struct napi_struc
|
@@ -1246,6 +1247,7 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
u8 *data, *new_data;
|
|
||||||
struct mtk_rx_dma *rxd, trxd;
|
|
||||||
int done = 0, bytes = 0;
|
|
||||||
+ bool uses_dsa = eth->netdev[0] && netdev_uses_dsa(eth->netdev[0]);
|
|
||||||
|
|
||||||
while (done < budget) {
|
|
||||||
struct net_device *netdev;
|
|
||||||
unsigned int pktlen;
|
unsigned int pktlen;
|
||||||
dma_addr_t dma_addr;
|
dma_addr_t dma_addr;
|
||||||
int mac;
|
int mac;
|
||||||
@ -33,27 +26,26 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
ring = mtk_get_rx_ring(eth);
|
ring = mtk_get_rx_ring(eth);
|
||||||
if (unlikely(!ring))
|
if (unlikely(!ring))
|
||||||
@@ -1259,13 +1262,13 @@ static int mtk_poll_rx(struct napi_struc
|
@@ -1259,13 +1261,12 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* find out which mac the packet come from. values start at 1 */
|
/* find out which mac the packet come from. values start at 1 */
|
||||||
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
|
- if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
|
||||||
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628))
|
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) ||
|
||||||
|
+ (trxd.rxd4 & RX_DMA_SPECIAL_TAG))
|
||||||
mac = 0;
|
mac = 0;
|
||||||
- } else {
|
- } else {
|
||||||
- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
|
- mac = (trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
|
||||||
- RX_DMA_FPORT_MASK;
|
- RX_DMA_FPORT_MASK;
|
||||||
- mac--;
|
- mac--;
|
||||||
- }
|
- }
|
||||||
+ else if (uses_dsa)
|
|
||||||
+ mac = !(trxd.rxd4 >> 22);
|
|
||||||
+ else
|
+ else
|
||||||
+ mac = ((trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
|
+ mac = ((trxd.rxd4 >> RX_DMA_FPORT_SHIFT) &
|
||||||
+ RX_DMA_FPORT_MASK) - 1;
|
+ RX_DMA_FPORT_MASK) - 1;
|
||||||
|
|
||||||
if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
|
if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
|
||||||
!eth->netdev[mac]))
|
!eth->netdev[mac]))
|
||||||
@@ -2247,6 +2250,9 @@ static void mtk_gdm_config(struct mtk_et
|
@@ -2247,6 +2248,9 @@ static void mtk_gdm_config(struct mtk_et
|
||||||
|
|
||||||
val |= config;
|
val |= config;
|
||||||
|
|
||||||
@ -73,3 +65,11 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#define MTK_GDMA_ICS_EN BIT(22)
|
#define MTK_GDMA_ICS_EN BIT(22)
|
||||||
#define MTK_GDMA_TCS_EN BIT(21)
|
#define MTK_GDMA_TCS_EN BIT(21)
|
||||||
#define MTK_GDMA_UCS_EN BIT(20)
|
#define MTK_GDMA_UCS_EN BIT(20)
|
||||||
|
@@ -311,6 +312,7 @@
|
||||||
|
#define RX_DMA_L4_VALID_PDMA BIT(30) /* when PDMA is used */
|
||||||
|
#define RX_DMA_FPORT_SHIFT 19
|
||||||
|
#define RX_DMA_FPORT_MASK 0x7
|
||||||
|
+#define RX_DMA_SPECIAL_TAG BIT(22)
|
||||||
|
|
||||||
|
/* PHY Indirect Access Control registers */
|
||||||
|
#define MTK_PHY_IAC 0x10004
|
||||||
|
@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -1318,6 +1318,10 @@ static int mtk_poll_rx(struct napi_struc
|
@@ -1316,6 +1316,10 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
skb->protocol = eth_type_trans(skb, netdev);
|
skb->protocol = eth_type_trans(skb, netdev);
|
||||||
bytes += pktlen;
|
bytes += pktlen;
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,401 @@
|
|||||||
|
From: Felix Fietkau <nbd@nbd.name>
|
||||||
|
Date: Sun, 11 Oct 2020 22:28:32 +0200
|
||||||
|
Subject: [PATCH] net: ethernet: mediatek: mtk_eth_soc: add flow offloading
|
||||||
|
support
|
||||||
|
|
||||||
|
Only supports IPv4 for now
|
||||||
|
|
||||||
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||||
|
---
|
||||||
|
create mode 100644 drivers/net/ethernet/mediatek/mtk_offload.c
|
||||||
|
create mode 100644 drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
|
||||||
|
|
||||||
|
--- a/drivers/net/ethernet/mediatek/Makefile
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/Makefile
|
||||||
|
@@ -4,4 +4,4 @@
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_NET_MEDIATEK_SOC) += mtk_eth.o
|
||||||
|
-mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o
|
||||||
|
+mtk_eth-y := mtk_eth_soc.o mtk_sgmii.o mtk_eth_path.o mtk_ppe.o mtk_ppe_debugfs.o mtk_offload.o
|
||||||
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
|
@@ -19,6 +19,8 @@
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/pinctrl/devinfo.h>
|
||||||
|
#include <linux/phylink.h>
|
||||||
|
+#include <linux/netfilter.h>
|
||||||
|
+#include <net/netfilter/nf_flow_table.h>
|
||||||
|
#include <net/dsa.h>
|
||||||
|
|
||||||
|
#include "mtk_eth_soc.h"
|
||||||
|
@@ -1324,8 +1326,12 @@ static int mtk_poll_rx(struct napi_struc
|
||||||
|
(trxd.rxd2 & RX_DMA_VTAG))
|
||||||
|
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
|
||||||
|
RX_DMA_VID(trxd.rxd3));
|
||||||
|
- skb_record_rx_queue(skb, 0);
|
||||||
|
- napi_gro_receive(napi, skb);
|
||||||
|
+ if (mtk_offload_check_rx(eth, skb, trxd.rxd4) == 0) {
|
||||||
|
+ skb_record_rx_queue(skb, 0);
|
||||||
|
+ napi_gro_receive(napi, skb);
|
||||||
|
+ } else {
|
||||||
|
+ dev_kfree_skb(skb);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
skip_rx:
|
||||||
|
ring->data[idx] = new_data;
|
||||||
|
@@ -2858,6 +2864,25 @@ static int mtk_set_rxnfc(struct net_devi
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+mtk_flow_offload(enum flow_offload_type type, struct flow_offload *flow,
|
||||||
|
+ struct flow_offload_hw_path *src,
|
||||||
|
+ struct flow_offload_hw_path *dest)
|
||||||
|
+{
|
||||||
|
+ struct mtk_mac *mac = netdev_priv(src->dev);
|
||||||
|
+ struct mtk_eth *eth = mac->hw;
|
||||||
|
+
|
||||||
|
+ if (!eth->soc->offload_version)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (src->dev->base_addr != dest->dev->base_addr)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ mac = netdev_priv(src->dev);
|
||||||
|
+
|
||||||
|
+ return mtk_flow_offload_add(eth, type, flow, src, dest);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static const struct ethtool_ops mtk_ethtool_ops = {
|
||||||
|
.get_link_ksettings = mtk_get_link_ksettings,
|
||||||
|
.set_link_ksettings = mtk_set_link_ksettings,
|
||||||
|
@@ -2889,6 +2914,7 @@ static const struct net_device_ops mtk_n
|
||||||
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
|
.ndo_poll_controller = mtk_poll_controller,
|
||||||
|
#endif
|
||||||
|
+ .ndo_flow_offload = mtk_flow_offload,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
||||||
|
@@ -3154,6 +3180,10 @@ static int mtk_probe(struct platform_dev
|
||||||
|
eth->base + MTK_ETH_PPE_BASE, 2);
|
||||||
|
if (err)
|
||||||
|
goto err_free_dev;
|
||||||
|
+
|
||||||
|
+ err = mtk_flow_offload_init(eth);
|
||||||
|
+ if (err)
|
||||||
|
+ goto err_free_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MTK_MAX_DEVS; i++) {
|
||||||
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
|
@@ -929,6 +929,7 @@ struct mtk_eth {
|
||||||
|
int ip_align;
|
||||||
|
|
||||||
|
struct mtk_ppe ppe;
|
||||||
|
+ struct flow_offload __rcu **foe_flow_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* struct mtk_mac - the structure that holds the info about the MACs of the
|
||||||
|
@@ -973,4 +974,12 @@ int mtk_gmac_sgmii_path_setup(struct mtk
|
||||||
|
int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
|
||||||
|
int mtk_gmac_rgmii_path_setup(struct mtk_eth *eth, int mac_id);
|
||||||
|
|
||||||
|
+int mtk_flow_offload_init(struct mtk_eth *eth);
|
||||||
|
+int mtk_flow_offload_add(struct mtk_eth *eth,
|
||||||
|
+ enum flow_offload_type type,
|
||||||
|
+ struct flow_offload *flow,
|
||||||
|
+ struct flow_offload_hw_path *src,
|
||||||
|
+ struct flow_offload_hw_path *dest);
|
||||||
|
+int mtk_offload_check_rx(struct mtk_eth *eth, struct sk_buff *skb, u32 rxd4);
|
||||||
|
+
|
||||||
|
#endif /* MTK_ETH_H */
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_offload.c
|
||||||
|
@@ -0,0 +1,146 @@
|
||||||
|
+/* This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; version 2 of the License
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2018 John Crispin <john@phrozen.org>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <net/netfilter/nf_flow_table.h>
|
||||||
|
+#include "mtk_eth_soc.h"
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+mtk_offload_prepare_v4(struct mtk_eth *eth, struct mtk_foe_entry *entry,
|
||||||
|
+ struct flow_offload_tuple *s_tuple,
|
||||||
|
+ struct flow_offload_tuple *d_tuple,
|
||||||
|
+ struct flow_offload_hw_path *src,
|
||||||
|
+ struct flow_offload_hw_path *dest)
|
||||||
|
+{
|
||||||
|
+ int dest_port = 1;
|
||||||
|
+
|
||||||
|
+ if (dest->dev == eth->netdev[1])
|
||||||
|
+ dest_port = 2;
|
||||||
|
+
|
||||||
|
+ mtk_foe_entry_prepare(entry, MTK_PPE_PKT_TYPE_IPV4_HNAPT, s_tuple->l4proto,
|
||||||
|
+ dest_port, dest->eth_src, dest->eth_dest);
|
||||||
|
+ mtk_foe_entry_set_ipv4_tuple(entry, false,
|
||||||
|
+ s_tuple->src_v4.s_addr, s_tuple->src_port,
|
||||||
|
+ s_tuple->dst_v4.s_addr, s_tuple->dst_port);
|
||||||
|
+ mtk_foe_entry_set_ipv4_tuple(entry, true,
|
||||||
|
+ d_tuple->dst_v4.s_addr, d_tuple->dst_port,
|
||||||
|
+ d_tuple->src_v4.s_addr, d_tuple->src_port);
|
||||||
|
+
|
||||||
|
+ if (dest->flags & FLOW_OFFLOAD_PATH_PPPOE)
|
||||||
|
+ mtk_foe_entry_set_pppoe(entry, dest->pppoe_sid);
|
||||||
|
+
|
||||||
|
+ if (dest->flags & FLOW_OFFLOAD_PATH_VLAN)
|
||||||
|
+ mtk_foe_entry_set_vlan(entry, dest->vlan_id);
|
||||||
|
+
|
||||||
|
+ if (dest->flags & FLOW_OFFLOAD_PATH_DSA)
|
||||||
|
+ mtk_foe_entry_set_dsa(entry, dest->dsa_port);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mtk_flow_offload_add(struct mtk_eth *eth,
|
||||||
|
+ enum flow_offload_type type,
|
||||||
|
+ struct flow_offload *flow,
|
||||||
|
+ struct flow_offload_hw_path *src,
|
||||||
|
+ struct flow_offload_hw_path *dest)
|
||||||
|
+{
|
||||||
|
+ struct flow_offload_tuple *otuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple;
|
||||||
|
+ struct flow_offload_tuple *rtuple = &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple;
|
||||||
|
+ struct mtk_foe_entry orig, reply;
|
||||||
|
+ u32 ohash, rhash, timestamp;
|
||||||
|
+
|
||||||
|
+ if (otuple->l4proto != IPPROTO_TCP && otuple->l4proto != IPPROTO_UDP)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (type == FLOW_OFFLOAD_DEL) {
|
||||||
|
+ ohash = (unsigned long)flow->priv;
|
||||||
|
+ rhash = ohash >> 16;
|
||||||
|
+ ohash &= 0xffff;
|
||||||
|
+ mtk_foe_entry_clear(ð->ppe, ohash);
|
||||||
|
+ mtk_foe_entry_clear(ð->ppe, rhash);
|
||||||
|
+ rcu_assign_pointer(eth->foe_flow_table[ohash], NULL);
|
||||||
|
+ rcu_assign_pointer(eth->foe_flow_table[rhash], NULL);
|
||||||
|
+ synchronize_rcu();
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (otuple->l3proto) {
|
||||||
|
+ case AF_INET:
|
||||||
|
+ if (mtk_offload_prepare_v4(eth, &orig, otuple, rtuple, src, dest) ||
|
||||||
|
+ mtk_offload_prepare_v4(eth, &reply, rtuple, otuple, dest, src))
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ timestamp = mtk_r32(eth, 0x0010);
|
||||||
|
+
|
||||||
|
+ ohash = mtk_foe_entry_commit(ð->ppe, &orig, timestamp);
|
||||||
|
+ if (ohash < 0)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ rhash = mtk_foe_entry_commit(ð->ppe, &reply, timestamp);
|
||||||
|
+ if (rhash < 0) {
|
||||||
|
+ mtk_foe_entry_clear(ð->ppe, ohash);
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ rcu_assign_pointer(eth->foe_flow_table[ohash], flow);
|
||||||
|
+ rcu_assign_pointer(eth->foe_flow_table[rhash], flow);
|
||||||
|
+
|
||||||
|
+ ohash |= rhash << 16;
|
||||||
|
+ flow->priv = (void *)(unsigned long)ohash;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void mtk_offload_keepalive(struct mtk_eth *eth, unsigned int hash)
|
||||||
|
+{
|
||||||
|
+ struct flow_offload *flow;
|
||||||
|
+
|
||||||
|
+ rcu_read_lock();
|
||||||
|
+ flow = rcu_dereference(eth->foe_flow_table[hash]);
|
||||||
|
+ if (flow)
|
||||||
|
+ flow->timeout = jiffies + 30 * HZ;
|
||||||
|
+ rcu_read_unlock();
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mtk_offload_check_rx(struct mtk_eth *eth, struct sk_buff *skb, u32 rxd4)
|
||||||
|
+{
|
||||||
|
+ unsigned int hash;
|
||||||
|
+
|
||||||
|
+ switch (FIELD_GET(MTK_RXD4_PPE_CPU_REASON, rxd4)) {
|
||||||
|
+ case MTK_PPE_CPU_REASON_KEEPALIVE_UC_OLD_HDR:
|
||||||
|
+ case MTK_PPE_CPU_REASON_KEEPALIVE_MC_NEW_HDR:
|
||||||
|
+ case MTK_PPE_CPU_REASON_KEEPALIVE_DUP_OLD_HDR:
|
||||||
|
+ hash = FIELD_GET(MTK_RXD4_FOE_ENTRY, rxd4);
|
||||||
|
+ mtk_offload_keepalive(eth, hash);
|
||||||
|
+ return -1;
|
||||||
|
+ case MTK_PPE_CPU_REASON_PACKET_SAMPLING:
|
||||||
|
+ return -1;
|
||||||
|
+ default:
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mtk_flow_offload_init(struct mtk_eth *eth)
|
||||||
|
+{
|
||||||
|
+ eth->foe_flow_table = devm_kcalloc(eth->dev, MTK_PPE_ENTRIES,
|
||||||
|
+ sizeof(*eth->foe_flow_table),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+
|
||||||
|
+ if (!eth->foe_flow_table)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
|
||||||
|
@@ -375,6 +375,8 @@ int mtk_ppe_init(struct mtk_ppe *ppe, st
|
||||||
|
|
||||||
|
ppe->foe_table = foe;
|
||||||
|
|
||||||
|
+ mtk_ppe_debugfs_init(ppe);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--- a/drivers/net/ethernet/mediatek/mtk_ppe.h
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.h
|
||||||
|
@@ -271,4 +271,7 @@ int mtk_foe_entry_set_pppoe(struct mtk_f
|
||||||
|
int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_foe_entry *entry,
|
||||||
|
u16 timestamp);
|
||||||
|
|
||||||
|
+/* internal */
|
||||||
|
+int mtk_ppe_debugfs_init(struct mtk_ppe *ppe);
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
|
||||||
|
@@ -0,0 +1,114 @@
|
||||||
|
+/* This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published by
|
||||||
|
+ * the Free Software Foundation; version 2 of the License
|
||||||
|
+ *
|
||||||
|
+ * This program is distributed in the hope that it will be useful,
|
||||||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ * GNU General Public License for more details.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2014-2016 Sean Wang <sean.wang@mediatek.com>
|
||||||
|
+ * Copyright (C) 2016-2017 John Crispin <blogic@openwrt.org>
|
||||||
|
+ * Copyright (C) 2020 Felix Fietkau <nbd@nbd.name>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/debugfs.h>
|
||||||
|
+#include "mtk_eth_soc.h"
|
||||||
|
+
|
||||||
|
+static const char *mtk_foe_entry_state_str[] = {
|
||||||
|
+ "INVALID",
|
||||||
|
+ "UNBIND",
|
||||||
|
+ "BIND",
|
||||||
|
+ "FIN"
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static const char *mtk_foe_packet_type_str[] = {
|
||||||
|
+ "IPV4_HNAPT",
|
||||||
|
+ "IPV4_HNAT",
|
||||||
|
+ "IPV6_1T_ROUTE",
|
||||||
|
+ "IPV4_DSLITE",
|
||||||
|
+ "IPV6_3T_ROUTE",
|
||||||
|
+ "IPV6_5T_ROUTE",
|
||||||
|
+ "IPV6_6RD",
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+#define es(entry) (mtk_foe_entry_state_str[FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1)])
|
||||||
|
+//#define ei(entry, end) (MTK_PPE_TBL_SZ - (int)(end - entry))
|
||||||
|
+#define pt(entry) (mtk_foe_packet_type_str[FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1)])
|
||||||
|
+
|
||||||
|
+static int mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private)
|
||||||
|
+{
|
||||||
|
+ struct mtk_ppe *ppe = m->private;
|
||||||
|
+ int i, count;
|
||||||
|
+
|
||||||
|
+ for (i = 0, count = 0; i < MTK_PPE_ENTRIES; i++) {
|
||||||
|
+ struct mtk_foe_entry *entry = &ppe->foe_table[i];
|
||||||
|
+
|
||||||
|
+ if (!FIELD_GET(MTK_FOE_IB1_STATE, entry->ib1))
|
||||||
|
+ continue;
|
||||||
|
+
|
||||||
|
+ if (FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1) ==
|
||||||
|
+ MTK_PPE_PKT_TYPE_IPV4_HNAPT) {
|
||||||
|
+ struct mtk_foe_ipv4 *ip4 = &entry->ipv4;
|
||||||
|
+ struct mtk_foe_mac_info *l2 = &ip4->l2;
|
||||||
|
+
|
||||||
|
+ __be32 saddr = htonl(ip4->orig.src_ip);
|
||||||
|
+ __be32 daddr = htonl(ip4->orig.dest_ip);
|
||||||
|
+ __be32 nsaddr = htonl(ip4->new.src_ip);
|
||||||
|
+ __be32 ndaddr = htonl(ip4->new.dest_ip);
|
||||||
|
+ unsigned char h_dest[ETH_ALEN];
|
||||||
|
+ unsigned char h_source[ETH_ALEN];
|
||||||
|
+
|
||||||
|
+ *((__be32 *) h_source) = htonl(l2->src_mac_hi);
|
||||||
|
+ *((__be16*) &h_source[4]) = htons(l2->src_mac_lo);
|
||||||
|
+ *((__be32*) h_dest) = htonl(l2->dest_mac_hi);
|
||||||
|
+ *((__be16*) &h_dest[4]) = htons(l2->dest_mac_lo);
|
||||||
|
+ seq_printf(m,
|
||||||
|
+ "(%x)0x%05x|state=%s|type=%s|"
|
||||||
|
+ "%pI4:%d->%pI4:%d=>%pI4:%d->%pI4:%d|%pM=>%pM|"
|
||||||
|
+ "etype=0x%04x|info1=0x%x|info2=0x%x|"
|
||||||
|
+ "vlan1=%d|vlan2=%d\n",
|
||||||
|
+ count, i, es(entry), pt(entry),
|
||||||
|
+ &saddr, ip4->orig.src_port,
|
||||||
|
+ &daddr, ip4->orig.dest_port,
|
||||||
|
+ &nsaddr, ip4->new.src_port,
|
||||||
|
+ &ndaddr, ip4->new.dest_port,
|
||||||
|
+ h_source, h_dest,
|
||||||
|
+ ntohs(l2->etype),
|
||||||
|
+ entry->ib1,
|
||||||
|
+ ip4->ib2,
|
||||||
|
+ l2->vlan1,
|
||||||
|
+ l2->vlan2);
|
||||||
|
+ count++;
|
||||||
|
+ } else
|
||||||
|
+ seq_printf(m, "0x%05x state=%s\n", count, es(entry));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mtk_ppe_debugfs_foe_open(struct inode *inode, struct file *file)
|
||||||
|
+{
|
||||||
|
+ return single_open(file, mtk_ppe_debugfs_foe_show, inode->i_private);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct file_operations mtk_ppe_debugfs_foe_fops = {
|
||||||
|
+ .open = mtk_ppe_debugfs_foe_open,
|
||||||
|
+ .read = seq_read,
|
||||||
|
+ .llseek = seq_lseek,
|
||||||
|
+ .release = single_release,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int mtk_ppe_debugfs_init(struct mtk_ppe *ppe)
|
||||||
|
+{
|
||||||
|
+ struct dentry *root;
|
||||||
|
+
|
||||||
|
+ root = debugfs_create_dir("mtk_ppe", NULL);
|
||||||
|
+ if (!root)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ debugfs_create_file("entries", S_IRUGO, root, ppe, &mtk_ppe_debugfs_foe_fops);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
@ -111,7 +111,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
struct mvpp2_port *port = netdev_priv(dev);
|
struct mvpp2_port *port = netdev_priv(dev);
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -446,9 +446,10 @@ static void mtk_mac_link_down(struct phy
|
@@ -448,9 +448,10 @@ static void mtk_mac_link_down(struct phy
|
||||||
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +199,10 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
+ * @duplex: link duplex
|
+ * @duplex: link duplex
|
||||||
+ * @tx_pause: link transmit pause enablement status
|
+ * @tx_pause: link transmit pause enablement status
|
||||||
+ * @rx_pause: link receive pause enablement status
|
+ * @rx_pause: link receive pause enablement status
|
||||||
+ *
|
*
|
||||||
|
- * If @mode is not an in-band negotiation mode (as defined by
|
||||||
|
- * phylink_autoneg_inband()), allow the link to come up. If @phy
|
||||||
|
- * is non-%NULL, configure Energy Efficient Ethernet by calling
|
||||||
+ * Configure the MAC for an established link.
|
+ * Configure the MAC for an established link.
|
||||||
+ *
|
+ *
|
||||||
+ * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link
|
+ * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link
|
||||||
@ -211,10 +214,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
|||||||
+ * Note that when 802.3z in-band negotiation is in use, it is possible
|
+ * Note that when 802.3z in-band negotiation is in use, it is possible
|
||||||
+ * that the user wishes to override the pause settings, and this should
|
+ * that the user wishes to override the pause settings, and this should
|
||||||
+ * be allowed when considering the implementation of this method.
|
+ * be allowed when considering the implementation of this method.
|
||||||
*
|
+ *
|
||||||
- * If @mode is not an in-band negotiation mode (as defined by
|
|
||||||
- * phylink_autoneg_inband()), allow the link to come up. If @phy
|
|
||||||
- * is non-%NULL, configure Energy Efficient Ethernet by calling
|
|
||||||
+ * If in-band negotiation mode is disabled, allow the link to come up. If
|
+ * If in-band negotiation mode is disabled, allow the link to come up. If
|
||||||
+ * @phy is non-%NULL, configure Energy Efficient Ethernet by calling
|
+ * @phy is non-%NULL, configure Energy Efficient Ethernet by calling
|
||||||
* phy_init_eee() and perform appropriate MAC configuration for EEE.
|
* phy_init_eee() and perform appropriate MAC configuration for EEE.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -37,12 +37,13 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
@@ -2486,6 +2487,12 @@ static int mtk_hw_init(struct mtk_eth *e
|
@@ -2482,6 +2483,13 @@ static int mtk_hw_init(struct mtk_eth *e
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_disable_pm;
|
goto err_disable_pm;
|
||||||
|
|
||||||
+ if (of_dma_is_coherent(eth->dev->of_node)) {
|
+ if (of_dma_is_coherent(eth->dev->of_node)) {
|
||||||
+ u32 mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA;
|
+ u32 mask = ETHSYS_DMA_AG_MAP_PDMA | ETHSYS_DMA_AG_MAP_QDMA |
|
||||||
|
+ ETHSYS_DMA_AG_MAP_PPE;
|
||||||
+
|
+
|
||||||
+ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, mask, mask);
|
+ regmap_update_bits(eth->ethsys, ETHSYS_DMA_AG_MAP, mask, mask);
|
||||||
+ }
|
+ }
|
||||||
@ -50,7 +51,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
|
if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
|
||||||
ret = device_reset(eth->dev);
|
ret = device_reset(eth->dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -3088,6 +3095,16 @@ static int mtk_probe(struct platform_dev
|
@@ -3080,6 +3088,16 @@ static int mtk_probe(struct platform_dev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
|
||||||
@@ -426,6 +426,11 @@
|
@@ -435,6 +435,12 @@
|
||||||
#define RSTCTRL_FE BIT(6)
|
#define RSTCTRL_FE BIT(6)
|
||||||
#define RSTCTRL_PPE BIT(31)
|
#define RSTCTRL_PPE BIT(31)
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|||||||
+#define ETHSYS_DMA_AG_MAP 0x408
|
+#define ETHSYS_DMA_AG_MAP 0x408
|
||||||
+#define ETHSYS_DMA_AG_MAP_PDMA BIT(0)
|
+#define ETHSYS_DMA_AG_MAP_PDMA BIT(0)
|
||||||
+#define ETHSYS_DMA_AG_MAP_QDMA BIT(1)
|
+#define ETHSYS_DMA_AG_MAP_QDMA BIT(1)
|
||||||
|
+#define ETHSYS_DMA_AG_MAP_PPE BIT(2)
|
||||||
+
|
+
|
||||||
/* SGMII subsystem config registers */
|
/* SGMII subsystem config registers */
|
||||||
/* Register to auto-negotiation restart */
|
/* Register to auto-negotiation restart */
|
||||||
|
@ -14,7 +14,7 @@ Signed-off-by: René van Dorst <opensource@vdorst.com>
|
|||||||
|
|
||||||
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
|
||||||
@@ -2887,6 +2887,7 @@ static const struct net_device_ops mtk_n
|
@@ -2919,6 +2919,7 @@ static const struct net_device_ops mtk_n
|
||||||
|
|
||||||
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
|
||||||
{
|
{
|
||||||
@ -22,7 +22,7 @@ Signed-off-by: René van Dorst <opensource@vdorst.com>
|
|||||||
const __be32 *_id = of_get_property(np, "reg", NULL);
|
const __be32 *_id = of_get_property(np, "reg", NULL);
|
||||||
struct phylink *phylink;
|
struct phylink *phylink;
|
||||||
int phy_mode, id, err;
|
int phy_mode, id, err;
|
||||||
@@ -2979,6 +2980,9 @@ static int mtk_add_mac(struct mtk_eth *e
|
@@ -3011,6 +3012,9 @@ static int mtk_add_mac(struct mtk_eth *e
|
||||||
|
|
||||||
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user