Commit 5a558611 authored by Ong Boon Leong's avatar Ong Boon Leong Committed by David S. Miller
Browse files

net: stmmac: support FPE link partner hand-shaking procedure



In order to discover whether remote station supports frame preemption,
local station sends verify mPacket and expects response mPacket in
return from the remote station.

So, we add the functions to send and handle event when verify mPacket
and response mPacket are exchanged between the networked stations.

The mechanism to handle different FPE states between local and remote
station (link partner) is implemented using workqueue which starts a
task each time there is some sign of verify & response mPacket exchange
as check in FPE IRQ event. The task retries couple of times to try to
spot the states that both stations are ready to enter FPE ON. This allows
different end points to enable FPE at different time and verify-response
mPacket can happen asynchronously. Ultimately, the task will only turn
FPE ON when local station have both exchange response in both directions.

Thanks to Voon Weifeng for implementing the core functions for detecting
FPE events and send mPacket and phylink related change.

Signed-off-by: default avatarOng Boon Leong <boon.leong.ong@intel.com>
Co-developed-by: default avatarVoon Weifeng <weifeng.voon@intel.com>
Signed-off-by: default avatarVoon Weifeng <weifeng.voon@intel.com>
Co-developed-by: default avatarTan Tee Min <tee.min.tan@intel.com>
Signed-off-by: default avatarTan Tee Min <tee.min.tan@intel.com>
Co-developed-by: default avatarMohammad Athari Bin Ismail <mohammad.athari.ismail@intel.com>
Signed-off-by: default avatarMohammad Athari Bin Ismail <mohammad.athari.ismail@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent da1da87f
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -315,6 +315,13 @@ enum dma_irq_status {
#define	CORE_IRQ_RX_PATH_IN_LPI_MODE	(1 << 2)
#define	CORE_IRQ_RX_PATH_EXIT_LPI_MODE	(1 << 3)

/* FPE defines */
#define FPE_EVENT_UNKNOWN		0
#define FPE_EVENT_TRSP			BIT(0)
#define FPE_EVENT_TVER			BIT(1)
#define FPE_EVENT_RRSP			BIT(2)
#define FPE_EVENT_RVER			BIT(3)

#define CORE_IRQ_MTL_RX_OVERFLOW	BIT(8)

/* Physical Coding Sublayer */
+8 −0
Original line number Diff line number Diff line
@@ -53,6 +53,10 @@ static void dwmac4_core_init(struct mac_device_info *hw,
	if (hw->pcs)
		value |= GMAC_PCS_IRQ_DEFAULT;

	/* Enable FPE interrupt */
	if ((GMAC_HW_FEAT_FPESEL & readl(ioaddr + GMAC_HW_FEATURE3)) >> 26)
		value |= GMAC_INT_FPE_EN;

	writel(value, ioaddr + GMAC_INT_EN);
}

@@ -1245,6 +1249,8 @@ const struct stmmac_ops dwmac410_ops = {
	.config_l4_filter = dwmac4_config_l4_filter,
	.est_configure = dwmac5_est_configure,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
	.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
	.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
	.restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,
@@ -1294,6 +1300,8 @@ const struct stmmac_ops dwmac510_ops = {
	.config_l4_filter = dwmac4_config_l4_filter,
	.est_configure = dwmac5_est_configure,
	.fpe_configure = dwmac5_fpe_configure,
	.fpe_send_mpacket = dwmac5_fpe_send_mpacket,
	.fpe_irq_status = dwmac5_fpe_irq_status,
	.add_hw_vlan_rx_fltr = dwmac4_add_hw_vlan_rx_fltr,
	.del_hw_vlan_rx_fltr = dwmac4_del_hw_vlan_rx_fltr,
	.restore_hw_vlan_rx_fltr = dwmac4_restore_hw_vlan_rx_fltr,
+49 −0
Original line number Diff line number Diff line
@@ -707,3 +707,52 @@ void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
	value |= EFPE;
	writel(value, ioaddr + MAC_FPE_CTRL_STS);
}

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

	status = FPE_EVENT_UNKNOWN;

	value = readl(ioaddr + MAC_FPE_CTRL_STS);

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

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

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

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

	return status;
}

void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, enum stmmac_mpacket_type type)
{
	u32 value;

	value = readl(ioaddr + MAC_FPE_CTRL_STS);

	if (type == MPACKET_VERIFY) {
		value &= ~SRSP;
		value |= SVER;
	} else {
		value &= ~SVER;
		value |= SRSP;
	}

	writel(value, ioaddr + MAC_FPE_CTRL_STS);
}
+11 −0
Original line number Diff line number Diff line
@@ -12,6 +12,12 @@
#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
@@ -128,6 +134,8 @@
#define GMAC_RXQCTRL_VFFQ_SHIFT		17
#define GMAC_RXQCTRL_VFFQE		BIT(16)

#define GMAC_INT_FPE_EN			BIT(17)

int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp);
int dwmac5_safety_feat_irq_status(struct net_device *ndev,
		void __iomem *ioaddr, unsigned int asp,
@@ -145,5 +153,8 @@ void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
			   struct stmmac_extra_stats *x, u32 txqcnt);
void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
			  bool enable);
void dwmac5_fpe_send_mpacket(void __iomem *ioaddr,
			     enum stmmac_mpacket_type type);
int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev);

#endif /* __DWMAC5_H__ */
+7 −0
Original line number Diff line number Diff line
@@ -397,6 +397,9 @@ struct stmmac_ops {
			       struct stmmac_extra_stats *x, u32 txqcnt);
	void (*fpe_configure)(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
			      bool enable);
	void (*fpe_send_mpacket)(void __iomem *ioaddr,
				 enum stmmac_mpacket_type type);
	int (*fpe_irq_status)(void __iomem *ioaddr, struct net_device *dev);
};

#define stmmac_core_init(__priv, __args...) \
@@ -497,6 +500,10 @@ struct stmmac_ops {
	stmmac_do_void_callback(__priv, mac, est_irq_status, __args)
#define stmmac_fpe_configure(__priv, __args...) \
	stmmac_do_void_callback(__priv, mac, fpe_configure, __args)
#define stmmac_fpe_send_mpacket(__priv, __args...) \
	stmmac_do_void_callback(__priv, mac, fpe_send_mpacket, __args)
#define stmmac_fpe_irq_status(__priv, __args...) \
	stmmac_do_callback(__priv, mac, fpe_irq_status, __args)

/* PTP and HW Timer helpers */
struct stmmac_hwtimestamp {
Loading