[PATCH v2 net-next] net: stmmac: xgmac3+: add FPE handshaking support

From: Jianheng Zhang
Date: Tue Dec 12 2023 - 09:05:41 EST


Adds the HW specific support for Frame Preemption handshaking on XGMAC3+
cores.

Signed-off-by: Jianheng Zhang <Jianheng.Zhang@xxxxxxxxxxxx>
---
v2:
- updating the FPE debug message to use netdev_dbg()
v1: https://lore.kernel.org/all/CY5PR12MB63726FED738099761A9B81E7BF8FA@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/
---
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h | 6 ++
.../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 66 ++++++++++++++++++----
2 files changed, 61 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index 207ff17..306d15b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -194,6 +194,12 @@
#define XGMAC_MDIO_DATA 0x00000204
#define XGMAC_MDIO_C22P 0x00000220
#define XGMAC_FPE_CTRL_STS 0x00000280
+#define XGMAC_TRSP BIT(19)
+#define XGMAC_TVER BIT(18)
+#define XGMAC_RRSP BIT(17)
+#define XGMAC_RVER BIT(16)
+#define XGMAC_SRSP BIT(2)
+#define XGMAC_SVER BIT(1)
#define XGMAC_EFPE BIT(0)
#define XGMAC_ADDRx_HIGH(x) (0x00000300 + (x) * 0x8)
#define XGMAC_ADDR_MAX 32
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index eb48211..2f14f9b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -1439,22 +1439,64 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
{
u32 value;

- if (!enable) {
- value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
+ if (enable) {
+ cfg->fpe_csr = XGMAC_EFPE;
+ value = readl(ioaddr + XGMAC_RXQ_CTRL1);
+ value &= ~XGMAC_RQ;
+ value |= (num_rxq - 1) << XGMAC_RQ_SHIFT;
+ writel(value, ioaddr + XGMAC_RXQ_CTRL1);
+ } else {
+ cfg->fpe_csr = 0;
+ }
+ writel(cfg->fpe_csr, ioaddr + XGMAC_FPE_CTRL_STS);
+}

- value &= ~XGMAC_EFPE;
+static int dwxgmac3_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
+{
+ u32 value;
+ int status;

- writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
- return;
+ status = FPE_EVENT_UNKNOWN;
+
+ /* Reads from the XGMAC_FPE_CTRL_STS register should only be performed
+ * here, since the status flags of MAC_FPE_CTRL_STS are "clear on read"
+ */
+ value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
+
+ if (value & XGMAC_TRSP) {
+ status |= FPE_EVENT_TRSP;
+ netdev_dbg(dev, "FPE: Respond mPacket is transmitted\n");
}

- value = readl(ioaddr + XGMAC_RXQ_CTRL1);
- value &= ~XGMAC_RQ;
- value |= (num_rxq - 1) << XGMAC_RQ_SHIFT;
- writel(value, ioaddr + XGMAC_RXQ_CTRL1);
+ if (value & XGMAC_TVER) {
+ status |= FPE_EVENT_TVER;
+ netdev_dbg(dev, "FPE: Verify mPacket is transmitted\n");
+ }
+
+ if (value & XGMAC_RRSP) {
+ status |= FPE_EVENT_RRSP;
+ netdev_dbg(dev, "FPE: Respond mPacket is received\n");
+ }
+
+ if (value & XGMAC_RVER) {
+ status |= FPE_EVENT_RVER;
+ netdev_dbg(dev, "FPE: Verify mPacket is received\n");
+ }
+
+ return status;
+}
+
+static void dwxgmac3_fpe_send_mpacket(void __iomem *ioaddr,
+ struct stmmac_fpe_cfg *cfg,
+ enum stmmac_mpacket_type type)
+{
+ u32 value = cfg->fpe_csr;
+
+ if (type == MPACKET_VERIFY)
+ value |= XGMAC_SVER;
+ else if (type == MPACKET_RESPONSE)
+ value |= XGMAC_SRSP;

- value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
- value |= XGMAC_EFPE;
writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
}

@@ -1503,6 +1545,8 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *
.config_l4_filter = dwxgmac2_config_l4_filter,
.set_arp_offload = dwxgmac2_set_arp_offload,
.fpe_configure = dwxgmac3_fpe_configure,
+ .fpe_send_mpacket = dwxgmac3_fpe_send_mpacket,
+ .fpe_irq_status = dwxgmac3_fpe_irq_status,
};

static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
--
1.8.3.1