blob: 0ca0e3aaf7c3d25042e4ba98b3c739118f51c83e [file] [log] [blame]
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1992,6 +1992,17 @@ static void mtk_tx_set_dma_desc_v3(struc
trace_printk("[%s] skb_shinfo(skb)->nr_frags=%x HNAT_SKB_CB2(skb)->magic=%x txd4=%x<-----\n",
__func__, skb_shinfo(skb)->nr_frags, HNAT_SKB_CB2(skb)->magic, data);
#endif
+
+ /* forward to eip197 if this packet is going to encrypt */
+#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_hnat_cdrt(skb) && is_magic_tag_valid(skb)))
+#else
+ if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_tnl_cdrt(skb) && is_tnl_tag_valid(skb)))
+#endif // hnat
+ {
+ data &= ((~TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT);
+ data |= (EIP197_QDMA_TPORT & TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT;
+ }
WRITE_ONCE(desc->txd4, data);
data = 0;
@@ -2014,6 +2025,21 @@ static void mtk_tx_set_dma_desc_v3(struc
WRITE_ONCE(desc->txd7, 0);
WRITE_ONCE(desc->txd8, 0);
+
+#if defined(CONFIG_NET_MEDIATEK_HNAT) || defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+ if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) {
+ /* carry cdrt index for encryption */
+ data = (skb_hnat_cdrt(skb) & TX_DMA_CDRT_MASK) << TX_DMA_CDRT_SHIFT;
+ WRITE_ONCE(desc->txd8, data);
+ skb_hnat_magic_tag(skb) = 0;
+ }
+#else
+ if (unlikely(skb->inner_protocol == IPPROTO_ESP && skb_tnl_cdrt(skb) && is_tnl_tag_valid(skb))) {
+ data = (skb_tnl_cdrt(skb) & TX_DMA_CDRT_MASK) << TX_DMA_CDRT_SHIFT;
+ WRITE_ONCE(desc->txd8, data);
+ skb_tnl_magic_tag(skb) = 0;
+ }
+#endif // hnat
}
static void mtk_tx_set_pdma_desc(struct sk_buff *skb, struct net_device *dev, void *txd,
@@ -2491,6 +2517,7 @@ static int mtk_poll_rx(struct napi_struc
skb_hnat_alg(skb) = 0;
skb_hnat_filled(skb) = 0;
+ skb_hnat_set_cdrt(skb, 0);
skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
skb_hnat_set_tops(skb, 0);
skb_hnat_set_is_decap(skb, 0);
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -1078,6 +1078,9 @@ static unsigned int hnat_ipv4_get_nextho
return 0;
}
+ if (!skb_hnat_cdrt(skb) && dst && dst_xfrm(dst))
+ return 0;
+
rcu_read_lock_bh();
nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
@@ -1302,6 +1305,9 @@ static inline void hnat_fill_offload_eng
*/
entry->ipv4_hnapt.tport_id = NR_TDMA_QDMA_TPORT;
entry->ipv4_hnapt.tops_entry = skb_hnat_tops(skb);
+ } else if (skb_hnat_cdrt(skb)) {
+ entry->ipv4_hnapt.tport_id = NR_EIP197_QDMA_TPORT;
+ entry->ipv4_hnapt.cdrt_id = skb_hnat_cdrt(skb);
} else {
return;
}
@@ -1311,6 +1317,79 @@ static inline void hnat_fill_offload_eng
#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
}
+int hnat_bind_crypto_entry(struct sk_buff *skb, const struct net_device *dev) {
+ struct foe_entry *foe;
+ struct foe_entry entry = { 0 };
+ struct ethhdr *eth = eth_hdr(skb);
+ u32 gmac = NR_DISCARD;
+ struct mtk_mac *mac = netdev_priv(dev);
+
+ if (skb_hnat_tops(skb) && mtk_tnl_encap_offload)
+ mtk_tnl_encap_offload(skb);
+
+ foe = &hnat_priv->foe_table_cpu[skb_hnat_ppe(skb)][skb_hnat_entry(skb)];
+
+ hnat_get_filled_unbind_entry(skb, &entry);
+ entry.bfib1.cah = 1;
+ entry.bfib1.time_stamp = (hnat_priv->data->version == MTK_HNAT_V2 ||
+ hnat_priv->data->version == MTK_HNAT_V3) ?
+ readl(hnat_priv->fe_base + 0x0010) & (0xFF) :
+ readl(hnat_priv->fe_base + 0x0010) & (0x7FFF);
+ entry.ipv4_hnapt.iblk2.port_ag =
+ (hnat_priv->data->version == MTK_HNAT_V2 ||
+ hnat_priv->data->version == MTK_HNAT_V3) ? 0xf : 0x3f;
+
+ if (IS_LAN(dev)) {
+ if (IS_BOND_MODE)
+ gmac = ((skb_hnat_entry(skb) >> 1) % hnat_priv->gmac_num) ?
+ NR_GMAC2_PORT : NR_GMAC1_PORT;
+ else
+ gmac = NR_GMAC1_PORT;
+ } else if (IS_LAN2(dev)) {
+ gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
+ } else if (IS_WAN(dev)) {
+ if (IS_GMAC1_MODE)
+ gmac = NR_GMAC1_PORT;
+ else
+ gmac = (mac->id == MTK_GMAC2_ID) ? NR_GMAC2_PORT : NR_GMAC3_PORT;
+ } else {
+ pr_notice("Unknown case of dp, iif=%x --> %s\n", skb_hnat_iface(skb), dev->name);
+ return -1;
+ }
+
+ entry.ipv4_hnapt.iblk2.mibf = 1;
+ entry.ipv4_hnapt.iblk2.dp = gmac;
+ entry.ipv4_hnapt.iblk2.port_mg =
+ (hnat_priv->data->version == MTK_HNAT_V1_1) ? 0x3f : 0;
+ entry.bfib1.ttl = 1;
+ entry.bfib1.state = BIND;
+
+ hnat_fill_offload_engine_entry(skb, &entry, dev);
+
+ if (!skb_hnat_tops(skb)) {
+ entry.ipv4_hnapt.dmac_hi = swab32(*((u32 *)eth->h_dest));
+ entry.ipv4_hnapt.dmac_lo = swab16(*((u16 *)&eth->h_dest[4]));
+ entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source));
+ entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)&eth->h_source[4]));
+ }
+
+ wmb();
+
+ if (entry_hnat_is_bound(foe))
+ return 0;
+
+ memcpy(foe, &entry, sizeof(entry));
+
+ if (hnat_priv->data->per_flow_accounting &&
+ skb_hnat_entry(skb) < hnat_priv->foe_etry_num &&
+ skb_hnat_ppe(skb) < CFG_PPE_NUM)
+ memset(&hnat_priv->acct[skb_hnat_ppe(skb)][skb_hnat_entry(skb)],
+ 0, sizeof(struct mib_entry));
+
+ return 0;
+}
+EXPORT_SYMBOL(hnat_bind_crypto_entry);
+
static unsigned int skb_to_hnat_info(struct sk_buff *skb,
const struct net_device *dev,
struct foe_entry *foe,
@@ -2363,6 +2442,7 @@ int mtk_sw_nat_hook_rx(struct sk_buff *s
skb_hnat_alg(skb) = 0;
skb_hnat_set_tops(skb, 0);
+ skb_hnat_set_cdrt(skb, 0);
skb_hnat_magic_tag(skb) = HNAT_MAGIC_TAG;
if (skb_hnat_iface(skb) == FOE_MAGIC_WED0)
@@ -2449,7 +2529,8 @@ static unsigned int mtk_hnat_accel_type(
* is from local_out which is also filtered in sanity check.
*/
dst = skb_dst(skb);
- if (dst && dst_xfrm(dst))
+ if (dst && dst_xfrm(dst)
+ && (!mtk_crypto_offloadable || !mtk_crypto_offloadable(skb)))
return 0;
ct = nf_ct_get(skb, &ctinfo);
@@ -2853,6 +2934,14 @@ static unsigned int mtk_hnat_nf_post_rou
}
}
+ /* we are not support protocols other than IPv4 TCP for crypto offload yet */
+ if (skb_hnat_is_decrypt(skb)
+ && (ntohs(skb->protocol) != ETH_P_IP
+ || ip_hdr(skb)->protocol != IPPROTO_TCP)) {
+ skb_hnat_alg(skb) = 1;
+ return 0;
+ }
+
if (!IS_LAN_GRP(out) && !IS_WAN(out) && !IS_EXT(out))
is_virt_dev = true;
@@ -3162,7 +3251,10 @@ mtk_hnat_ipv4_nf_local_out(void *priv, s
if (iph->protocol == IPPROTO_IPV6) {
entry->udib1.pkt_type = IPV6_6RD;
hnat_set_head_frags(state, skb, 0, hnat_set_alg);
- } else if (!skb_hnat_tops(skb)) {
+ } else if (is_magic_tag_valid(skb)
+ && (skb_hnat_cdrt(skb) || skb_hnat_tops(skb))) {
+ hnat_set_head_frags(state, skb, 0, hnat_set_alg);
+ } else {
hnat_set_head_frags(state, skb, 1, hnat_set_alg);
}
--- a/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/nf_hnat_mtk.h
@@ -46,7 +46,8 @@ struct hnat_desc {
u32 amsdu : 1;
u32 tops : 6;
u32 is_decap : 1;
- u32 resv3 : 12;
+ u32 cdrt : 8;
+ u32 resv3 : 4;
u32 magic_tag_protect : 16;
} __packed;
#elif defined(CONFIG_MEDIATEK_NETSYS_RX_V2)
@@ -99,12 +100,16 @@ struct hnat_desc {
#define skb_hnat_is_encap(skb) (!skb_hnat_is_decap(skb))
#define skb_hnat_set_tops(skb, tops) ((skb_hnat_tops(skb)) = (tops))
#define skb_hnat_set_is_decap(skb, is_decap) ((skb_hnat_is_decap(skb)) = (is_decap))
+#define skb_hnat_cdrt(skb) (((struct hnat_desc *)((skb)->head))->cdrt)
+#define skb_hnat_set_cdrt(skb, cdrt) ((skb_hnat_cdrt(skb)) = (cdrt))
#else /* !defined(CONFIG_MEDIATEK_NETSYS_V3) */
#define skb_hnat_tops(skb) (0)
#define skb_hnat_is_decap(skb) (0)
#define skb_hnat_is_encap(skb) (0)
#define skb_hnat_set_tops(skb, tops)
#define skb_hnat_set_is_decap(skb, is_decap)
+#define skb_hnat_cdrt(skb) (0)
+#define skb_hnat_set_cdrt(skb, cdrt)
#endif /* defined(CONFIG_MEDIATEK_NETSYS_V3) */
#define skb_hnat_magic(skb) (((struct hnat_desc *)(skb->head))->magic)
#define skb_hnat_reason(skb) (((struct hnat_desc *)(skb->head))->crsn)
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -54,6 +54,8 @@ int (*mtk_tnl_decap_offload)(struct sk_b
EXPORT_SYMBOL(mtk_tnl_decap_offload);
bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb) = NULL;
EXPORT_SYMBOL(mtk_tnl_decap_offloadable);
+bool (*mtk_crypto_offloadable)(struct sk_buff *skb) = NULL;
+EXPORT_SYMBOL(mtk_crypto_offloadable);
static void hnat_sma_build_entry(struct timer_list *t)
{
--- a/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -1146,6 +1146,8 @@ enum FoeIpAct {
#define NR_WDMA1_PORT 9
#define NR_WDMA2_PORT 13
#define NR_GMAC3_PORT 15
+#define NR_EIP197_TPORT 2
+#define NR_EIP197_QDMA_TPORT 3
#define NR_TDMA_TPORT 4
#define NR_TDMA_QDMA_TPORT 5
#define LAN_DEV_NAME hnat_priv->lan
@@ -1298,6 +1300,8 @@ extern int qos_toggle;
extern int (*mtk_tnl_encap_offload)(struct sk_buff *skb);
extern int (*mtk_tnl_decap_offload)(struct sk_buff *skb);
extern bool (*mtk_tnl_decap_offloadable)(struct sk_buff *skb);
+extern bool (*mtk_crypto_offloadable)(struct sk_buff *skb);
+extern int hnat_bind_crypto_entry(struct sk_buff *skb, const struct net_device *dev);
int ext_if_add(struct extdev_entry *ext_entry);
int ext_if_del(struct extdev_entry *ext_entry);
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -592,6 +592,10 @@
#define MTK_QDMA_GMAC2_QID 8
#define MTK_QDMA_GMAC3_QID 6
+/* QDMA V2 descriptor txd8 */
+#define TX_DMA_CDRT_SHIFT 0
+#define TX_DMA_CDRT_MASK 0xff
+
/* QDMA V2 descriptor txd6 */
#define TX_DMA_INS_VLAN_V2 BIT(16)
@@ -601,6 +605,9 @@
#define TX_DMA_SPTAG_V3 BIT(27)
/* QDMA V2 descriptor txd4 */
+#define EIP197_QDMA_TPORT 3
+#define TX_DMA_TPORT_SHIFT 0
+#define TX_DMA_TPORT_MASK 0xf
#define TX_DMA_FPORT_SHIFT_V2 8
#define TX_DMA_FPORT_MASK_V2 0xf
#define TX_DMA_SWC_V2 BIT(30)
@@ -1063,6 +1070,43 @@
#define MT7628_SDM_MAC_ADRL (MT7628_SDM_OFFSET + 0x0c)
#define MT7628_SDM_MAC_ADRH (MT7628_SDM_OFFSET + 0x10)
+#if !defined(CONFIG_NET_MEDIATEK_HNAT) && !defined(CONFIG_NET_MEDIATEK_HNAT_MODULE)
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+struct tnl_desc {
+ u32 entry : 15;
+ u32 filled : 3;
+ u32 crsn : 5;
+ u32 resv1 : 3;
+ u32 sport : 4;
+ u32 resv2 : 1;
+ u32 alg : 1;
+ u32 iface : 8;
+ u32 wdmaid : 2;
+ u32 rxid : 2;
+ u32 wcid : 16;
+ u32 bssid : 8;
+ u32 usr_info : 16;
+ u32 tid : 4;
+ u32 is_fixedrate : 1;
+ u32 is_prior : 1;
+ u32 is_sp : 1;
+ u32 hf : 1;
+ u32 amsdu : 1;
+ u32 tops : 6;
+ u32 is_decap : 1;
+ u32 cdrt : 8;
+ u32 resv3 : 4;
+ u32 magic_tag_protect : 16;
+} __packed;
+
+#define TNL_MAGIC_TAG 0x6789
+#define skb_tnl_cdrt(skb) (((struct tnl_desc *)((skb)->head))->cdrt)
+#define skb_tnl_set_cdrt(skb, cdrt) ((skb_tnl_cdrt(skb)) = (cdrt))
+#define skb_tnl_magic_tag(skb) (((struct tnl_desc *)((skb)->head))->magic_tag_protect)
+#define is_tnl_tag_valid(skb) (skb_tnl_magic_tag(skb) == TNL_MAGIC_TAG)
+#endif // NetsysV3
+#endif // hnat
+
struct mtk_rx_dma {
unsigned int rxd1;
unsigned int rxd2;