| --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c |
| +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c |
| @@ -1857,6 +1857,12 @@ 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); |
| + |
| + /* forward to eip197 if this packet is going to encrypt */ |
| + if (unlikely(skb_hnat_cdrt(skb) && is_magic_tag_valid(skb))) { |
| + data &= ((~TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT); |
| + data |= (EIP197_QDMA_TPORT & TX_DMA_TPORT_MASK) << TX_DMA_TPORT_SHIFT; |
| + } |
| #endif |
| WRITE_ONCE(desc->txd4, data); |
| |
| @@ -1880,6 +1886,17 @@ 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_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 { |
| + WRITE_ONCE(desc->txd8, 0); |
| + } |
| +#endif |
| } |
| |
| static void mtk_tx_set_dma_desc(struct sk_buff *skb, struct net_device *dev, void *txd, |
| @@ -2307,6 +2324,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 |
| @@ -1077,6 +1077,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); |
| @@ -1301,6 +1304,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; |
| } |
| @@ -1310,6 +1316,75 @@ 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; |
| + |
| + 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 = NR_GMAC2_PORT; |
| + } else if (IS_WAN(dev)) { |
| + gmac = (IS_GMAC1_MODE) ? NR_GMAC1_PORT : NR_GMAC2_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 *)ð->h_dest[4])); |
| + entry.ipv4_hnapt.smac_hi = swab32(*((u32 *)eth->h_source)); |
| + entry.ipv4_hnapt.smac_lo = swab16(*((u16 *)ð->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, |
| @@ -2359,6 +2434,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) |
| @@ -2445,7 +2521,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); |
| @@ -2849,6 +2926,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; |
| |
| @@ -3158,7 +3243,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 |
| @@ -49,6 +49,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 |
| @@ -1140,6 +1140,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 |
| @@ -1292,6 +1294,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 |
| @@ -558,6 +558,10 @@ |
| |
| #define MTK_QDMA_GMAC2_QID 8 |
| |
| +/* 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) |
| |
| @@ -567,6 +571,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) |