Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 744dfcb1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac-ptp'



Giuseppe Cavallaro says:

====================
stmmac: fix PTP support

This subset of patches aim to fix the PTP support
for the stmmac and especially for 4.x chip series.
While setting PTP on an ST box with 4.00a Ethernet
core, the kernel panics due to a broken settings
of the descriptors. The patches review the
register configuration, the algo used for configuring
the protocol, the way to get the timestamp inside
the RX/TX descriptors and, in the end, the statistics
displayed by ethtool.

V2: RESEND all the patches adding the Acked-by.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 24803f38 ee112c12
Loading
Loading
Loading
Loading
+14 −10
Original line number Diff line number Diff line
@@ -120,14 +120,17 @@ struct stmmac_extra_stats {
	unsigned long ip_csum_bypassed;
	unsigned long ipv4_pkt_rcvd;
	unsigned long ipv6_pkt_rcvd;
	unsigned long rx_msg_type_ext_no_ptp;
	unsigned long rx_msg_type_sync;
	unsigned long rx_msg_type_follow_up;
	unsigned long rx_msg_type_delay_req;
	unsigned long rx_msg_type_delay_resp;
	unsigned long rx_msg_type_pdelay_req;
	unsigned long rx_msg_type_pdelay_resp;
	unsigned long rx_msg_type_pdelay_follow_up;
	unsigned long no_ptp_rx_msg_type_ext;
	unsigned long ptp_rx_msg_type_sync;
	unsigned long ptp_rx_msg_type_follow_up;
	unsigned long ptp_rx_msg_type_delay_req;
	unsigned long ptp_rx_msg_type_delay_resp;
	unsigned long ptp_rx_msg_type_pdelay_req;
	unsigned long ptp_rx_msg_type_pdelay_resp;
	unsigned long ptp_rx_msg_type_pdelay_follow_up;
	unsigned long ptp_rx_msg_type_announce;
	unsigned long ptp_rx_msg_type_management;
	unsigned long ptp_rx_msg_pkt_reserved_type;
	unsigned long ptp_frame_type;
	unsigned long ptp_ver;
	unsigned long timestamp_dropped;
@@ -482,11 +485,12 @@ struct stmmac_ops {
/* PTP and HW Timer helpers */
struct stmmac_hwtimestamp {
	void (*config_hw_tstamping) (void __iomem *ioaddr, u32 data);
	u32 (*config_sub_second_increment) (void __iomem *ioaddr, u32 clk_rate);
	u32 (*config_sub_second_increment)(void __iomem *ioaddr, u32 ptp_clock,
					   int gmac4);
	int (*init_systime) (void __iomem *ioaddr, u32 sec, u32 nsec);
	int (*config_addend) (void __iomem *ioaddr, u32 addend);
	int (*adjust_systime) (void __iomem *ioaddr, u32 sec, u32 nsec,
			       int add_sub);
			       int add_sub, int gmac4);
	 u64(*get_systime) (void __iomem *ioaddr);
};

+12 −8
Original line number Diff line number Diff line
@@ -155,14 +155,18 @@
#define	ERDES4_L3_L4_FILT_NO_MATCH_MASK	GENMASK(27, 26)

/* Extended RDES4 message type definitions */
#define RDES_EXT_NO_PTP			0
#define RDES_EXT_SYNC			1
#define RDES_EXT_FOLLOW_UP		2
#define RDES_EXT_DELAY_REQ		3
#define RDES_EXT_DELAY_RESP		4
#define RDES_EXT_PDELAY_REQ		5
#define RDES_EXT_PDELAY_RESP		6
#define RDES_EXT_PDELAY_FOLLOW_UP	7
#define RDES_EXT_NO_PTP			0x0
#define RDES_EXT_SYNC			0x1
#define RDES_EXT_FOLLOW_UP		0x2
#define RDES_EXT_DELAY_REQ		0x3
#define RDES_EXT_DELAY_RESP		0x4
#define RDES_EXT_PDELAY_REQ		0x5
#define RDES_EXT_PDELAY_RESP		0x6
#define RDES_EXT_PDELAY_FOLLOW_UP	0x7
#define RDES_PTP_ANNOUNCE		0x8
#define RDES_PTP_MANAGEMENT		0x9
#define RDES_PTP_SIGNALING		0xa
#define RDES_PTP_PKT_RESERVED_TYPE	0xf

/* Basic descriptor structure for normal and alternate descriptors */
struct dma_desc {
+74 −21
Original line number Diff line number Diff line
@@ -123,22 +123,29 @@ static int dwmac4_wrback_get_rx_status(void *data, struct stmmac_extra_stats *x,
		x->ipv4_pkt_rcvd++;
	if (rdes1 & RDES1_IPV6_HEADER)
		x->ipv6_pkt_rcvd++;
	if (message_type == RDES_EXT_SYNC)
		x->rx_msg_type_sync++;

	if (message_type == RDES_EXT_NO_PTP)
		x->no_ptp_rx_msg_type_ext++;
	else if (message_type == RDES_EXT_SYNC)
		x->ptp_rx_msg_type_sync++;
	else if (message_type == RDES_EXT_FOLLOW_UP)
		x->rx_msg_type_follow_up++;
		x->ptp_rx_msg_type_follow_up++;
	else if (message_type == RDES_EXT_DELAY_REQ)
		x->rx_msg_type_delay_req++;
		x->ptp_rx_msg_type_delay_req++;
	else if (message_type == RDES_EXT_DELAY_RESP)
		x->rx_msg_type_delay_resp++;
		x->ptp_rx_msg_type_delay_resp++;
	else if (message_type == RDES_EXT_PDELAY_REQ)
		x->rx_msg_type_pdelay_req++;
		x->ptp_rx_msg_type_pdelay_req++;
	else if (message_type == RDES_EXT_PDELAY_RESP)
		x->rx_msg_type_pdelay_resp++;
		x->ptp_rx_msg_type_pdelay_resp++;
	else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
		x->rx_msg_type_pdelay_follow_up++;
	else
		x->rx_msg_type_ext_no_ptp++;
		x->ptp_rx_msg_type_pdelay_follow_up++;
	else if (message_type == RDES_PTP_ANNOUNCE)
		x->ptp_rx_msg_type_announce++;
	else if (message_type == RDES_PTP_MANAGEMENT)
		x->ptp_rx_msg_type_management++;
	else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
		x->ptp_rx_msg_pkt_reserved_type++;

	if (rdes1 & RDES1_PTP_PACKET_TYPE)
		x->ptp_frame_type++;
@@ -204,14 +211,18 @@ static void dwmac4_rd_enable_tx_timestamp(struct dma_desc *p)

static int dwmac4_wrback_get_tx_timestamp_status(struct dma_desc *p)
{
	return (p->des3 & TDES3_TIMESTAMP_STATUS)
		>> TDES3_TIMESTAMP_STATUS_SHIFT;
	/* Context type from W/B descriptor must be zero */
	if (p->des3 & TDES3_CONTEXT_TYPE)
		return -EINVAL;

	/* Tx Timestamp Status is 1 so des0 and des1'll have valid values */
	if (p->des3 & TDES3_TIMESTAMP_STATUS)
		return 0;

	return 1;
}

/*  NOTE: For RX CTX bit has to be checked before
 *  HAVE a specific function for TX and another one for RX
 */
static u64 dwmac4_wrback_get_timestamp(void *desc, u32 ats)
static inline u64 dwmac4_get_timestamp(void *desc, u32 ats)
{
	struct dma_desc *p = (struct dma_desc *)desc;
	u64 ns;
@@ -223,12 +234,54 @@ static u64 dwmac4_wrback_get_timestamp(void *desc, u32 ats)
	return ns;
}

static int dwmac4_context_get_rx_timestamp_status(void *desc, u32 ats)
static int dwmac4_rx_check_timestamp(void *desc)
{
	struct dma_desc *p = (struct dma_desc *)desc;
	u32 own, ctxt;
	int ret = 1;

	own = p->des3 & RDES3_OWN;
	ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR)
		>> RDES3_CONTEXT_DESCRIPTOR_SHIFT);

	return (p->des1 & RDES1_TIMESTAMP_AVAILABLE)
		>> RDES1_TIMESTAMP_AVAILABLE_SHIFT;
	if (likely(!own && ctxt)) {
		if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
			/* Corrupted value */
			ret = -EINVAL;
		else
			/* A valid Timestamp is ready to be read */
			ret = 0;
	}

	/* Timestamp not ready */
	return ret;
}

static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats)
{
	struct dma_desc *p = (struct dma_desc *)desc;
	int ret = -EINVAL;

	/* Get the status from normal w/b descriptor */
	if (likely(p->des3 & TDES3_RS1V)) {
		if (likely(p->des1 & RDES1_TIMESTAMP_AVAILABLE)) {
			int i = 0;

			/* Check if timestamp is OK from context descriptor */
			do {
				ret = dwmac4_rx_check_timestamp(desc);
				if (ret < 0)
					goto exit;
				i++;

			} while ((ret == 1) || (i < 10));

			if (i == 10)
				ret = -EBUSY;
		}
	}
exit:
	return ret;
}

static void dwmac4_rd_init_rx_desc(struct dma_desc *p, int disable_rx_ic,
@@ -373,8 +426,8 @@ const struct stmmac_desc_ops dwmac4_desc_ops = {
	.get_rx_frame_len = dwmac4_wrback_get_rx_frame_len,
	.enable_tx_timestamp = dwmac4_rd_enable_tx_timestamp,
	.get_tx_timestamp_status = dwmac4_wrback_get_tx_timestamp_status,
	.get_timestamp = dwmac4_wrback_get_timestamp,
	.get_rx_timestamp_status = dwmac4_context_get_rx_timestamp_status,
	.get_rx_timestamp_status = dwmac4_wrback_get_rx_timestamp_status,
	.get_timestamp = dwmac4_get_timestamp,
	.set_tx_ic = dwmac4_rd_set_tx_ic,
	.prepare_tx_desc = dwmac4_rd_prepare_tx_desc,
	.prepare_tso_tx_desc = dwmac4_rd_prepare_tso_tx_desc,
+4 −0
Original line number Diff line number Diff line
@@ -59,10 +59,13 @@
#define TDES3_CTXT_TCMSSV		BIT(26)

/* TDES3 Common */
#define	TDES3_RS1V			BIT(26)
#define	TDES3_RS1V_SHIFT		26
#define TDES3_LAST_DESCRIPTOR		BIT(28)
#define TDES3_LAST_DESCRIPTOR_SHIFT	28
#define TDES3_FIRST_DESCRIPTOR		BIT(29)
#define TDES3_CONTEXT_TYPE		BIT(30)
#define	TDES3_CONTEXT_TYPE_SHIFT	30

/* TDS3 use for both format (read and write back) */
#define TDES3_OWN			BIT(31)
@@ -117,6 +120,7 @@
#define RDES3_LAST_DESCRIPTOR		BIT(28)
#define RDES3_FIRST_DESCRIPTOR		BIT(29)
#define RDES3_CONTEXT_DESCRIPTOR	BIT(30)
#define RDES3_CONTEXT_DESCRIPTOR_SHIFT	30

/* RDES3 (read format) */
#define RDES3_BUFFER1_VALID_ADDR	BIT(24)
+18 −10
Original line number Diff line number Diff line
@@ -150,22 +150,30 @@ static void enh_desc_get_ext_status(void *data, struct stmmac_extra_stats *x,
			x->ipv4_pkt_rcvd++;
		if (rdes4 & ERDES4_IPV6_PKT_RCVD)
			x->ipv6_pkt_rcvd++;
		if (message_type == RDES_EXT_SYNC)
			x->rx_msg_type_sync++;

		if (message_type == RDES_EXT_NO_PTP)
			x->no_ptp_rx_msg_type_ext++;
		else if (message_type == RDES_EXT_SYNC)
			x->ptp_rx_msg_type_sync++;
		else if (message_type == RDES_EXT_FOLLOW_UP)
			x->rx_msg_type_follow_up++;
			x->ptp_rx_msg_type_follow_up++;
		else if (message_type == RDES_EXT_DELAY_REQ)
			x->rx_msg_type_delay_req++;
			x->ptp_rx_msg_type_delay_req++;
		else if (message_type == RDES_EXT_DELAY_RESP)
			x->rx_msg_type_delay_resp++;
			x->ptp_rx_msg_type_delay_resp++;
		else if (message_type == RDES_EXT_PDELAY_REQ)
			x->rx_msg_type_pdelay_req++;
			x->ptp_rx_msg_type_pdelay_req++;
		else if (message_type == RDES_EXT_PDELAY_RESP)
			x->rx_msg_type_pdelay_resp++;
			x->ptp_rx_msg_type_pdelay_resp++;
		else if (message_type == RDES_EXT_PDELAY_FOLLOW_UP)
			x->rx_msg_type_pdelay_follow_up++;
		else
			x->rx_msg_type_ext_no_ptp++;
			x->ptp_rx_msg_type_pdelay_follow_up++;
		else if (message_type == RDES_PTP_ANNOUNCE)
			x->ptp_rx_msg_type_announce++;
		else if (message_type == RDES_PTP_MANAGEMENT)
			x->ptp_rx_msg_type_management++;
		else if (message_type == RDES_PTP_PKT_RESERVED_TYPE)
			x->ptp_rx_msg_pkt_reserved_type++;

		if (rdes4 & ERDES4_PTP_FRAME_TYPE)
			x->ptp_frame_type++;
		if (rdes4 & ERDES4_PTP_VER)
Loading