summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mediatek/mtk_ppe.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/mediatek/mtk_ppe.c')
-rw-r--r--drivers/net/ethernet/mediatek/mtk_ppe.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe.c b/drivers/net/ethernet/mediatek/mtk_ppe.c
index ada852adc5f7..8451dc3fd00a 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe.c
@@ -705,7 +705,7 @@ mtk_foe_entry_commit_subflow(struct mtk_ppe *ppe, struct mtk_flow_entry *entry,
u32 ib1_mask = mtk_get_ib1_pkt_type_mask(ppe->eth) | MTK_FOE_IB1_UDP;
int type;
- flow_info = kzalloc(sizeof(*flow_info), GFP_ATOMIC);
+ flow_info = kzalloc_obj(*flow_info, GFP_ATOMIC);
if (!flow_info)
return;
@@ -918,7 +918,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index)
mib = dmam_alloc_coherent(ppe->dev, MTK_PPE_ENTRIES * sizeof(*mib),
&ppe->mib_phys, GFP_KERNEL);
if (!mib)
- return NULL;
+ goto err_free_l2_flows;
ppe->mib_table = mib;
@@ -926,7 +926,7 @@ struct mtk_ppe *mtk_ppe_init(struct mtk_eth *eth, void __iomem *base, int index)
GFP_KERNEL);
if (!acct)
- return NULL;
+ goto err_free_l2_flows;
ppe->acct_table = acct;
}
@@ -973,6 +973,36 @@ static void mtk_ppe_init_foe_table(struct mtk_ppe *ppe)
}
}
+void mtk_ppe_update_mtu(struct mtk_ppe *ppe, int mtu)
+{
+ int base;
+ u32 val;
+
+ if (!ppe)
+ return;
+
+ /* The PPE checks output frame size against per-tag-layer MTU limits,
+ * treating PPPoE and DSA tags just like 802.1Q VLAN tags. The Linux
+ * device MTU already accounts for PPPoE (PPPOE_SES_HLEN) and DSA tag
+ * overhead, but 802.1Q VLAN tags are handled transparently without
+ * being reflected by the lower device MTU being increased by 4.
+ * Use the maximum MTU across all GMAC interfaces so that PPE output
+ * frame limits are sufficiently high regardless of which port a flow
+ * egresses through.
+ */
+ base = ETH_HLEN + mtu;
+
+ val = FIELD_PREP(MTK_PPE_VLAN_MTU0_NONE, base) |
+ FIELD_PREP(MTK_PPE_VLAN_MTU0_1TAG, base + VLAN_HLEN);
+ ppe_w32(ppe, MTK_PPE_VLAN_MTU0, val);
+
+ val = FIELD_PREP(MTK_PPE_VLAN_MTU1_2TAG,
+ base + 2 * VLAN_HLEN) |
+ FIELD_PREP(MTK_PPE_VLAN_MTU1_3TAG,
+ base + 3 * VLAN_HLEN);
+ ppe_w32(ppe, MTK_PPE_VLAN_MTU1, val);
+}
+
void mtk_ppe_start(struct mtk_ppe *ppe)
{
u32 val;