From patchwork Thu Sep 8 19:33:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 12970559 X-Patchwork-Delegate: kuba@kernel.org Return-Path: From: Lorenzo Bianconi To: netdev@vger.kernel.org Cc: nbd@nbd.name, john@phrozen.org, sean.wang@mediatek.com, Mark-MC.Lee@mediatek.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, matthias.bgg@gmail.com, linux-mediatek@lists.infradead.org, lorenzo.bianconi@redhat.com, Bo.Jiao@mediatek.com, sujuan.chen@mediatek.com, ryder.Lee@mediatek.com, evelyn.tsai@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH net-next 05/12] net: ethernet: mtk_eth_soc: add the capability to run multiple ppe Date: Thu, 8 Sep 2022 21:33:39 +0200 Message-Id: X-Mailer: git-send-email 2.37.3 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org mt7986 chipset support multiple packet engines for wlan <-> eth packet forwarding. Co-developed-by: Bo Jiao Signed-off-by: Bo Jiao Co-developed-by: Sujuan Chen Signed-off-by: Sujuan Chen Signed-off-by: Lorenzo Bianconi --- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 ++++++++++++------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +- drivers/net/ethernet/mediatek/mtk_ppe.c | 14 +++++--- drivers/net/ethernet/mediatek/mtk_ppe.h | 9 +++-- .../net/ethernet/mediatek/mtk_ppe_debugfs.c | 8 ++--- .../net/ethernet/mediatek/mtk_ppe_offload.c | 13 +++---- 6 files changed, 48 insertions(+), 33 deletions(-) --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1871,7 +1871,7 @@ static int mtk_poll_rx(struct napi_struc reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4); if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED) - mtk_ppe_check_skb(eth->ppe, skb, hash); + mtk_ppe_check_skb(eth->ppe[0], skb, hash); if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) { if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) { @@ -2929,7 +2929,8 @@ static int mtk_open(struct net_device *d /* we run 2 netdevs on the same dma ring so we only bring it up once */ if (!refcount_read(ð->dma_refcnt)) { const struct mtk_soc_data *soc = eth->soc; - u32 gdm_config = MTK_GDMA_TO_PDMA; + u32 gdm_config; + int i; int err; err = mtk_start_dma(eth); @@ -2938,8 +2939,11 @@ static int mtk_open(struct net_device *d return err; } - if (soc->offload_version && mtk_ppe_start(eth->ppe) == 0) - gdm_config = soc->reg_map->gdma_to_ppe0; + for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) + mtk_ppe_start(eth->ppe[i]); + + gdm_config = soc->offload_version ? soc->reg_map->gdma_to_ppe0 + : MTK_GDMA_TO_PDMA; mtk_gdm_config(eth, gdm_config); @@ -2984,6 +2988,7 @@ static int mtk_stop(struct net_device *d { struct mtk_mac *mac = netdev_priv(dev); struct mtk_eth *eth = mac->hw; + int i; phylink_stop(mac->phylink); @@ -3011,8 +3016,8 @@ static int mtk_stop(struct net_device *d mtk_dma_free(eth); - if (eth->soc->offload_version) - mtk_ppe_stop(eth->ppe); + for (i = 0; i < ARRAY_SIZE(eth->ppe); i++) + mtk_ppe_stop(eth->ppe[i]); return 0; } @@ -4052,12 +4057,19 @@ static int mtk_probe(struct platform_dev } if (eth->soc->offload_version) { - u32 ppe_addr = eth->soc->reg_map->ppe_base; + u32 num_ppe; - eth->ppe = mtk_ppe_init(eth, eth->base + ppe_addr, 2); - if (!eth->ppe) { - err = -ENOMEM; - goto err_free_dev; + num_ppe = MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2) ? 2 : 1; + num_ppe = min_t(u32, ARRAY_SIZE(eth->ppe), num_ppe); + for (i = 0; i < num_ppe; i++) { + u32 ppe_addr = eth->soc->reg_map->ppe_base + i * 0x400; + + eth->ppe[i] = mtk_ppe_init(eth, eth->base + ppe_addr, + eth->soc->offload_version, i); + if (!eth->ppe[i]) { + err = -ENOMEM; + goto err_free_dev; + } } err = mtk_eth_offload_init(eth); --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h @@ -1111,7 +1111,7 @@ struct mtk_eth { int ip_align; - struct mtk_ppe *ppe; + struct mtk_ppe *ppe[2]; struct rhashtable flow_table; struct bpf_prog __rcu *prog; --- a/drivers/net/ethernet/mediatek/mtk_ppe.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe.c @@ -682,7 +682,7 @@ int mtk_foe_entry_idle_time(struct mtk_p } struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, - int version) + int version, int index) { const struct mtk_soc_data *soc = eth->soc; struct device *dev = eth->dev; @@ -717,7 +717,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_ if (!ppe->foe_flow) return NULL; - mtk_ppe_debugfs_init(ppe); + mtk_ppe_debugfs_init(ppe, index); return ppe; } @@ -738,10 +738,13 @@ static void mtk_ppe_init_foe_table(struc ppe->foe_table[i + skip[k]].ib1 |= MTK_FOE_IB1_STATIC; } -int mtk_ppe_start(struct mtk_ppe *ppe) +void mtk_ppe_start(struct mtk_ppe *ppe) { u32 val; + if (!ppe) + return; + mtk_ppe_init_foe_table(ppe); ppe_w32(ppe, MTK_PPE_TB_BASE, ppe->foe_phys); @@ -809,8 +812,6 @@ int mtk_ppe_start(struct mtk_ppe *ppe) ppe_w32(ppe, MTK_PPE_GLO_CFG, val); ppe_w32(ppe, MTK_PPE_DEFAULT_CPU_PORT, 0); - - return 0; } int mtk_ppe_stop(struct mtk_ppe *ppe) @@ -818,6 +819,9 @@ int mtk_ppe_stop(struct mtk_ppe *ppe) u32 val; int i; + if (!ppe) + return 0; + for (i = 0; i < MTK_PPE_ENTRIES; i++) ppe->foe_table[i].ib1 = FIELD_PREP(MTK_FOE_IB1_STATE, MTK_FOE_STATE_INVALID); --- a/drivers/net/ethernet/mediatek/mtk_ppe.h +++ b/drivers/net/ethernet/mediatek/mtk_ppe.h @@ -247,6 +247,7 @@ struct mtk_flow_entry { }; u8 type; s8 wed_index; + u8 ppe_index; u16 hash; union { struct mtk_foe_entry data; @@ -265,6 +266,7 @@ struct mtk_ppe { struct device *dev; void __iomem *base; int version; + char dirname[5]; struct mtk_foe_entry *foe_table; dma_addr_t foe_phys; @@ -277,8 +279,9 @@ struct mtk_ppe { void *acct_table; }; -struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int version); -int mtk_ppe_start(struct mtk_ppe *ppe); +struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, + int version, int index); +void mtk_ppe_start(struct mtk_ppe *ppe); int mtk_ppe_stop(struct mtk_ppe *ppe); void __mtk_ppe_check_skb(struct mtk_ppe *ppe, struct sk_buff *skb, u16 hash); @@ -317,6 +320,6 @@ int mtk_foe_entry_set_wdma(struct mtk_fo int mtk_foe_entry_commit(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); void mtk_foe_entry_clear(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); int mtk_foe_entry_idle_time(struct mtk_ppe *ppe, struct mtk_flow_entry *entry); -int mtk_ppe_debugfs_init(struct mtk_ppe *ppe); +int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index); #endif --- a/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c @@ -187,7 +187,7 @@ mtk_ppe_debugfs_foe_open_bind(struct ino inode->i_private); } -int mtk_ppe_debugfs_init(struct mtk_ppe *ppe) +int mtk_ppe_debugfs_init(struct mtk_ppe *ppe, int index) { static const struct file_operations fops_all = { .open = mtk_ppe_debugfs_foe_open_all, @@ -195,17 +195,17 @@ int mtk_ppe_debugfs_init(struct mtk_ppe .llseek = seq_lseek, .release = single_release, }; - static const struct file_operations fops_bind = { .open = mtk_ppe_debugfs_foe_open_bind, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; - struct dentry *root; - root = debugfs_create_dir("mtk_ppe", NULL); + snprintf(ppe->dirname, sizeof(ppe->dirname), "ppe%d", index); + + root = debugfs_create_dir(ppe->dirname, NULL); if (!root) return -ENOMEM; --- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c @@ -434,7 +434,7 @@ mtk_flow_offload_replace(struct mtk_eth memcpy(&entry->data, &foe, sizeof(entry->data)); entry->wed_index = wed_index; - err = mtk_foe_entry_commit(eth->ppe, entry); + err = mtk_foe_entry_commit(eth->ppe[entry->ppe_index], entry); if (err < 0) goto free; @@ -446,7 +446,7 @@ mtk_flow_offload_replace(struct mtk_eth return 0; clear: - mtk_foe_entry_clear(eth->ppe, entry); + mtk_foe_entry_clear(eth->ppe[entry->ppe_index], entry); free: kfree(entry); if (wed_index >= 0) @@ -464,7 +464,7 @@ mtk_flow_offload_destroy(struct mtk_eth if (!entry) return -ENOENT; - mtk_foe_entry_clear(eth->ppe, entry); + mtk_foe_entry_clear(eth->ppe[entry->ppe_index], entry); rhashtable_remove_fast(ð->flow_table, &entry->node, mtk_flow_ht_params); if (entry->wed_index >= 0) @@ -485,7 +485,7 @@ mtk_flow_offload_stats(struct mtk_eth *e if (!entry) return -ENOENT; - idle = mtk_foe_entry_idle_time(eth->ppe, entry); + idle = mtk_foe_entry_idle_time(eth->ppe[entry->ppe_index], entry); f->stats.lastused = jiffies - idle * HZ; return 0; @@ -537,7 +537,7 @@ mtk_eth_setup_tc_block(struct net_device struct flow_block_cb *block_cb; flow_setup_cb_t *cb; - if (!eth->ppe || !eth->ppe->foe_table) + if (!eth->soc->offload_version) return -EOPNOTSUPP; if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS) @@ -589,8 +589,5 @@ int mtk_eth_setup_tc(struct net_device * int mtk_eth_offload_init(struct mtk_eth *eth) { - if (!eth->ppe || !eth->ppe->foe_table) - return 0; - return rhashtable_init(ð->flow_table, &mtk_flow_ht_params); }