Commit 74a11428 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-stmmac-refactor-fpe-as-a-separate-module'

Furong Xu says:

====================
net: stmmac: Refactor FPE as a separate module

Refactor FPE implementation by moving common code for DWMAC4 and
DWXGMAC into a separate FPE module.

FPE implementation for DWMAC4 and DWXGMAC differs only for:
1) Offset address of MAC_FPE_CTRL_STS and MTL_FPE_CTRL_STS
2) FPRQ(Frame Preemption Residue Queue) field in MAC_RxQ_Ctrl1
3) Bit offset of Frame Preemption Interrupt Enable

Tested on DWMAC CORE 5.20a and DWXGMAC CORE 3.20a
====================

Link: https://patch.msgid.link/cover.1730449003.git.0x1207@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 72ea418b 77be7d73
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -6,7 +6,7 @@ stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
	      mmc_core.o stmmac_hwtstamp.o stmmac_ptp.o dwmac4_descs.o	\
	      dwmac4_dma.o dwmac4_lib.o dwmac4_core.o dwmac5.o hwif.o \
	      stmmac_tc.o dwxgmac2_core.o dwxgmac2_dma.o dwxgmac2_descs.o \
	      stmmac_xdp.o stmmac_est.o \
	      stmmac_xdp.o stmmac_est.o stmmac_fpe.o \
	      $(stmmac-y)

stmmac-$(CONFIG_STMMAC_SELFTESTS) += stmmac_selftests.o
+0 −1
Original line number Diff line number Diff line
@@ -69,7 +69,6 @@
#define GMAC_RXQCTRL_TACPQE		BIT(21)
#define GMAC_RXQCTRL_TACPQE_SHIFT	21
#define GMAC_RXQCTRL_FPRQ		GENMASK(26, 24)
#define GMAC_RXQCTRL_FPRQ_SHIFT		24

/* MAC Packet Filtering */
#define GMAC_PACKET_FILTER_PR		BIT(0)
+1 −10
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include "stmmac.h"
#include "stmmac_fpe.h"
#include "stmmac_pcs.h"
#include "dwmac4.h"
#include "dwmac5.h"
@@ -1261,11 +1262,6 @@ const struct stmmac_ops dwmac410_ops = {
	.set_arp_offload = dwmac4_set_arp_offload,
	.config_l3_filter = dwmac4_config_l3_filter,
	.config_l4_filter = dwmac4_config_l4_filter,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
	.fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
	.fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
	.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
	.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
	.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
@@ -1316,11 +1312,6 @@ const struct stmmac_ops dwmac510_ops = {
	.set_arp_offload = dwmac4_set_arp_offload,
	.config_l3_filter = dwmac4_config_l3_filter,
	.config_l4_filter = dwmac4_config_l4_filter,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
	.fpe_get_add_frag_size = dwmac5_fpe_get_add_frag_size,
	.fpe_set_add_frag_size = dwmac5_fpe_set_add_frag_size,
	.fpe_map_preemption_class = dwmac5_fpe_map_preemption_class,
	.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
	.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
+0 −150
Original line number Diff line number Diff line
@@ -572,153 +572,3 @@ int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
	writel(val, ioaddr + MAC_PPS_CONTROL);
	return 0;
}

void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
			  u32 num_txq, u32 num_rxq,
			  bool tx_enable, bool pmac_enable)
{
	u32 value;

	if (tx_enable) {
		cfg->fpe_csr = EFPE;
		value = readl(ioaddr + GMAC_RXQ_CTRL1);
		value &= ~GMAC_RXQCTRL_FPRQ;
		value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
		writel(value, ioaddr + GMAC_RXQ_CTRL1);
	} else {
		cfg->fpe_csr = 0;
	}
	writel(cfg->fpe_csr, ioaddr + MAC_FPE_CTRL_STS);

	value = readl(ioaddr + GMAC_INT_EN);

	if (pmac_enable) {
		if (!(value & GMAC_INT_FPE_EN)) {
			/* Dummy read to clear any pending masked interrupts */
			readl(ioaddr + MAC_FPE_CTRL_STS);

			value |= GMAC_INT_FPE_EN;
		}
	} else {
		value &= ~GMAC_INT_FPE_EN;
	}

	writel(value, ioaddr + GMAC_INT_EN);
}

int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
{
	u32 value;
	int status;

	status = FPE_EVENT_UNKNOWN;

	/* Reads from the MAC_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 + MAC_FPE_CTRL_STS);

	if (value & TRSP) {
		status |= FPE_EVENT_TRSP;
		netdev_dbg(dev, "FPE: Respond mPacket is transmitted\n");
	}

	if (value & TVER) {
		status |= FPE_EVENT_TVER;
		netdev_dbg(dev, "FPE: Verify mPacket is transmitted\n");
	}

	if (value & RRSP) {
		status |= FPE_EVENT_RRSP;
		netdev_dbg(dev, "FPE: Respond mPacket is received\n");
	}

	if (value & RVER) {
		status |= FPE_EVENT_RVER;
		netdev_dbg(dev, "FPE: Verify mPacket is received\n");
	}

	return status;
}

void dwmac5_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 |= SVER;
	else if (type == MPACKET_RESPONSE)
		value |= SRSP;

	writel(value, ioaddr + MAC_FPE_CTRL_STS);
}

int dwmac5_fpe_get_add_frag_size(const void __iomem *ioaddr)
{
	return FIELD_GET(DWMAC5_ADD_FRAG_SZ, readl(ioaddr + MTL_FPE_CTRL_STS));
}

void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size)
{
	u32 value;

	value = readl(ioaddr + MTL_FPE_CTRL_STS);
	writel(u32_replace_bits(value, add_frag_size, DWMAC5_ADD_FRAG_SZ),
	       ioaddr + MTL_FPE_CTRL_STS);
}

#define ALG_ERR_MSG "TX algorithm SP is not suitable for one-to-many mapping"
#define WEIGHT_ERR_MSG "TXQ weight %u differs across other TXQs in TC: [%u]"

int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
				    struct netlink_ext_ack *extack, u32 pclass)
{
	u32 val, offset, count, queue_weight, preemptible_txqs = 0;
	struct stmmac_priv *priv = netdev_priv(ndev);
	u32 num_tc = ndev->num_tc;

	if (!pclass)
		goto update_mapping;

	/* DWMAC CORE4+ can not program TC:TXQ mapping to hardware.
	 *
	 * Synopsys Databook:
	 * "The number of Tx DMA channels is equal to the number of Tx queues,
	 * and is direct one-to-one mapping."
	 */
	for (u32 tc = 0; tc < num_tc; tc++) {
		count = ndev->tc_to_txq[tc].count;
		offset = ndev->tc_to_txq[tc].offset;

		if (pclass & BIT(tc))
			preemptible_txqs |= GENMASK(offset + count - 1, offset);

		/* This is 1:1 mapping, go to next TC */
		if (count == 1)
			continue;

		if (priv->plat->tx_sched_algorithm == MTL_TX_ALGORITHM_SP) {
			NL_SET_ERR_MSG_MOD(extack, ALG_ERR_MSG);
			return -EINVAL;
		}

		queue_weight = priv->plat->tx_queues_cfg[offset].weight;

		for (u32 i = 1; i < count; i++) {
			if (priv->plat->tx_queues_cfg[offset + i].weight !=
			    queue_weight) {
				NL_SET_ERR_MSG_FMT_MOD(extack, WEIGHT_ERR_MSG,
						       queue_weight, tc);
				return -EINVAL;
			}
		}
	}

update_mapping:
	val = readl(priv->ioaddr + MTL_FPE_CTRL_STS);
	writel(u32_replace_bits(val, preemptible_txqs, DWMAC5_PREEMPTION_CLASS),
	       priv->ioaddr + MTL_FPE_CTRL_STS);

	return 0;
}
+0 −26
Original line number Diff line number Diff line
@@ -11,15 +11,6 @@
#define PRTYEN				BIT(1)
#define TMOUTEN				BIT(0)

#define MAC_FPE_CTRL_STS		0x00000234
#define TRSP				BIT(19)
#define TVER				BIT(18)
#define RRSP				BIT(17)
#define RVER				BIT(16)
#define SRSP				BIT(2)
#define SVER				BIT(1)
#define EFPE				BIT(0)

#define MAC_PPS_CONTROL			0x00000b70
#define PPS_MAXIDX(x)			((((x) + 1) * 8) - 1)
#define PPS_MINIDX(x)			((x) * 8)
@@ -39,12 +30,6 @@
#define MAC_PPSx_INTERVAL(x)		(0x00000b88 + ((x) * 0x10))
#define MAC_PPSx_WIDTH(x)		(0x00000b8c + ((x) * 0x10))

#define MTL_FPE_CTRL_STS		0x00000c90
/* Preemption Classification */
#define DWMAC5_PREEMPTION_CLASS		GENMASK(15, 8)
/* Additional Fragment Size of preempted frames */
#define DWMAC5_ADD_FRAG_SZ		GENMASK(1, 0)

#define MTL_RXP_CONTROL_STATUS		0x00000ca0
#define RXPI				BIT(31)
#define NPE				GENMASK(23, 16)
@@ -108,16 +93,5 @@ int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
			   struct stmmac_pps_cfg *cfg, bool enable,
			   u32 sub_second_inc, u32 systime_flags);
void dwmac5_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg *cfg,
			  u32 num_txq, u32 num_rxq,
			  bool tx_enable, bool pmac_enable);
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
			     struct stmmac_fpe_cfg *cfg,
			     enum stmmac_mpacket_type type);
int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);
int dwmac5_fpe_get_add_frag_size(const void __iomem *ioaddr);
void dwmac5_fpe_set_add_frag_size(void __iomem *ioaddr, u32 add_frag_size);
int dwmac5_fpe_map_preemption_class(struct net_device *ndev,
				    struct netlink_ext_ack *extack, u32 pclass);

#endif /* __DWMAC5_H__ */
Loading