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

Merge branch 'ptp-Add-generic-helper-functions'

Kurt Kanzenbach says:

====================
ptp: Add generic helper functions

in order to reduce code duplication (and cut'n'paste errors) in the ptp code of
DSA, Ethernet and Phy drivers, create helper functions and move them to
ptp_classify. This way all drivers can share the same implementation.

This is version four and contains bugfixes. Implemented as discussed [1] [2]
[3] [4].

Previous versions can be found here:

 * https://lkml.kernel.org/netdev/20200723074946.14253-1-kurt@linutronix.de/
 * https://lkml.kernel.org/netdev/20200727090601.6500-1-kurt@linutronix.de/
 * https://lkml.kernel.org/netdev/20200730080048.32553-1-kurt@linutronix.de/

Thanks,
Kurt

Changes sinve v3:

 * Coding style issues (Richard Cochran, Petr Machata)
 * Add better documentation (Grygorii Strashko)
 * Fix cpts code (Grygorii Strashko)
 * Use ntohs() for TI code (Grygorii Strashko)
 * Add tags

Changes since v2:

 * Make ptp_parse_header() work in all scenarios (Russell King)
 * Fix msgtype offset for ptp v1 packets

Changes since v1:

 * Fix Kconfig (Richard Cochran)
 * Include more drivers (Richard Cochran)

[1] - https://lkml.kernel.org/netdev/20200713140112.GB27934@hoboy/
[2] - https://lkml.kernel.org/netdev/20200720142146.GB16001@hoboy/
[3] - https://lkml.kernel.org/netdev/20200723074946.14253-1-kurt@linutronix.de/
[4] - https://lkml.kernel.org/netdev/20200729100257.GX1551@shell.armlinux.org.uk/


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents f3ae59c0 17060fb5
Loading
Loading
Loading
Loading
+13 −46
Original line number Diff line number Diff line
@@ -211,49 +211,20 @@ int mv88e6xxx_port_hwtstamp_get(struct dsa_switch *ds, int port,
		-EFAULT : 0;
}

/* Get the start of the PTP header in this skb */
static u8 *parse_ptp_header(struct sk_buff *skb, unsigned int type)
{
	u8 *data = skb_mac_header(skb);
	unsigned int offset = 0;

	if (type & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (type & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
		return NULL;
	}

	/* Ensure that the entire header is present in this packet. */
	if (skb->len + ETH_HLEN < offset + 34)
		return NULL;

	return data + offset;
}

/* Returns a pointer to the PTP header if the caller should time stamp,
 * or NULL if the caller should not.
 */
static u8 *mv88e6xxx_should_tstamp(struct mv88e6xxx_chip *chip, int port,
				   struct sk_buff *skb, unsigned int type)
static struct ptp_header *mv88e6xxx_should_tstamp(struct mv88e6xxx_chip *chip,
						  int port, struct sk_buff *skb,
						  unsigned int type)
{
	struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
	u8 *hdr;
	struct ptp_header *hdr;

	if (!chip->info->ptp_support)
		return NULL;

	hdr = parse_ptp_header(skb, type);
	hdr = ptp_parse_header(skb, type);
	if (!hdr)
		return NULL;

@@ -275,12 +246,11 @@ static int mv88e6xxx_ts_valid(u16 status)
static int seq_match(struct sk_buff *skb, u16 ts_seqid)
{
	unsigned int type = SKB_PTP_TYPE(skb);
	u8 *hdr = parse_ptp_header(skb, type);
	__be16 *seqid;
	struct ptp_header *hdr;

	seqid = (__be16 *)(hdr + OFF_PTP_SEQUENCE_ID);
	hdr = ptp_parse_header(skb, type);

	return ts_seqid == ntohs(*seqid);
	return ts_seqid == ntohs(hdr->sequence_id);
}

static void mv88e6xxx_get_rxts(struct mv88e6xxx_chip *chip,
@@ -357,9 +327,9 @@ static void mv88e6xxx_rxtstamp_work(struct mv88e6xxx_chip *chip,
				   &ps->rx_queue2);
}

static int is_pdelay_resp(u8 *msgtype)
static int is_pdelay_resp(const struct ptp_header *hdr)
{
	return (*msgtype & 0xf) == 3;
	return (hdr->tsmt & 0xf) == 3;
}

bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
@@ -367,7 +337,7 @@ bool mv88e6xxx_port_rxtstamp(struct dsa_switch *ds, int port,
{
	struct mv88e6xxx_port_hwtstamp *ps;
	struct mv88e6xxx_chip *chip;
	u8 *hdr;
	struct ptp_header *hdr;

	chip = ds->priv;
	ps = &chip->port_hwtstamp[port];
@@ -503,8 +473,7 @@ bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
{
	struct mv88e6xxx_chip *chip = ds->priv;
	struct mv88e6xxx_port_hwtstamp *ps = &chip->port_hwtstamp[port];
	__be16 *seq_ptr;
	u8 *hdr;
	struct ptp_header *hdr;

	if (!(skb_shinfo(clone)->tx_flags & SKBTX_HW_TSTAMP))
		return false;
@@ -513,15 +482,13 @@ bool mv88e6xxx_port_txtstamp(struct dsa_switch *ds, int port,
	if (!hdr)
		return false;

	seq_ptr = (__be16 *)(hdr + OFF_PTP_SEQUENCE_ID);

	if (test_and_set_bit_lock(MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
				  &ps->state))
		return false;

	ps->tx_skb = clone;
	ps->tx_tstamp_start = jiffies;
	ps->tx_seq_id = be16_to_cpup(seq_ptr);
	ps->tx_seq_id = be16_to_cpu(hdr->sequence_id);

	ptp_schedule_worker(chip->ptp_clock, 0);
	return true;
+7 −25
Original line number Diff line number Diff line
@@ -314,11 +314,9 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
			      u8 *p_message_type,
			      u16 *p_sequence_id)
{
	unsigned int offset = 0;
	unsigned int ptp_class;
	u8 *data;
	struct ptp_header *hdr;

	data = skb_mac_header(skb);
	ptp_class = ptp_classify_raw(skb);

	switch (ptp_class & PTP_CLASS_VMASK) {
@@ -329,30 +327,14 @@ static int mlxsw_sp_ptp_parse(struct sk_buff *skb,
		return -ERANGE;
	}

	if (ptp_class & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (ptp_class & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
		return -ERANGE;
	}

	/* PTP header is 34 bytes. */
	if (skb->len < offset + 34)
	hdr = ptp_parse_header(skb, ptp_class);
	if (!hdr)
		return -EINVAL;

	*p_message_type = data[offset] & 0x0f;
	*p_domain_number = data[offset + 4];
	*p_sequence_id = (u16)(data[offset + 30]) << 8 | data[offset + 31];
	*p_message_type	 = ptp_get_msgtype(hdr, ptp_class);
	*p_domain_number = hdr->domain_number;
	*p_sequence_id	 = be16_to_cpu(hdr->sequence_id);

	return 0;
}

+9 −28
Original line number Diff line number Diff line
@@ -748,42 +748,23 @@ EXPORT_SYMBOL_GPL(am65_cpts_rx_enable);
static int am65_skb_get_mtype_seqid(struct sk_buff *skb, u32 *mtype_seqid)
{
	unsigned int ptp_class = ptp_classify_raw(skb);
	u8 *msgtype, *data = skb->data;
	unsigned int offset = 0;
	__be16 *seqid;
	struct ptp_header *hdr;
	u8 msgtype;
	u16 seqid;

	if (ptp_class == PTP_CLASS_NONE)
		return 0;

	if (ptp_class & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (ptp_class & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
		return 0;
	}

	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
	hdr = ptp_parse_header(skb, ptp_class);
	if (!hdr)
		return 0;

	if (unlikely(ptp_class & PTP_CLASS_V1))
		msgtype = data + offset + OFF_PTP_CONTROL;
	else
		msgtype = data + offset;
	msgtype = ptp_get_msgtype(hdr, ptp_class);
	seqid	= ntohs(hdr->sequence_id);

	seqid = (__be16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
	*mtype_seqid = (*msgtype << AM65_CPTS_EVENT_1_MESSAGE_TYPE_SHIFT) &
	*mtype_seqid  = (msgtype << AM65_CPTS_EVENT_1_MESSAGE_TYPE_SHIFT) &
			AM65_CPTS_EVENT_1_MESSAGE_TYPE_MASK;
	*mtype_seqid |= (ntohs(*seqid) & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK);
	*mtype_seqid |= (seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK);

	return 1;
}
+14 −28
Original line number Diff line number Diff line
@@ -446,41 +446,22 @@ static const struct ptp_clock_info cpts_info = {
static int cpts_skb_get_mtype_seqid(struct sk_buff *skb, u32 *mtype_seqid)
{
	unsigned int ptp_class = ptp_classify_raw(skb);
	u8 *msgtype, *data = skb->data;
	unsigned int offset = 0;
	u16 *seqid;
	struct ptp_header *hdr;
	u8 msgtype;
	u16 seqid;

	if (ptp_class == PTP_CLASS_NONE)
		return 0;

	if (ptp_class & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (ptp_class & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
		return 0;
	}

	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
	hdr = ptp_parse_header(skb, ptp_class);
	if (!hdr)
		return 0;

	if (unlikely(ptp_class & PTP_CLASS_V1))
		msgtype = data + offset + OFF_PTP_CONTROL;
	else
		msgtype = data + offset;
	msgtype = ptp_get_msgtype(hdr, ptp_class);
	seqid	= ntohs(hdr->sequence_id);

	seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
	*mtype_seqid = (*msgtype & MESSAGE_TYPE_MASK) << MESSAGE_TYPE_SHIFT;
	*mtype_seqid |= (ntohs(*seqid) & SEQUENCE_ID_MASK) << SEQUENCE_ID_SHIFT;
	*mtype_seqid  = (msgtype & MESSAGE_TYPE_MASK) << MESSAGE_TYPE_SHIFT;
	*mtype_seqid |= (seqid & SEQUENCE_ID_MASK) << SEQUENCE_ID_SHIFT;

	return 1;
}
@@ -528,6 +509,11 @@ void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
	int ret;
	u64 ns;

	/* cpts_rx_timestamp() is called before eth_type_trans(), so
	 * skb MAC Hdr properties are not configured yet. Hence need to
	 * reset skb MAC header here
	 */
	skb_reset_mac_header(skb);
	ret = cpts_skb_get_mtype_seqid(skb, &skb_cb->skb_mtype_seqid);
	if (!ret)
		return;
+16 −54
Original line number Diff line number Diff line
@@ -798,51 +798,32 @@ static int decode_evnt(struct dp83640_private *dp83640,
	return parsed;
}

#define DP83640_PACKET_HASH_OFFSET	20
#define DP83640_PACKET_HASH_LEN		10

static int match(struct sk_buff *skb, unsigned int type, struct rxts *rxts)
{
	unsigned int offset = 0;
	u8 *msgtype, *data = skb_mac_header(skb);
	__be16 *seqid;
	struct ptp_header *hdr;
	u8 msgtype;
	u16 seqid;
	u16 hash;

	/* check sequenceID, messageType, 12 bit hash of offset 20-29 */

	if (type & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (type & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
	hdr = ptp_parse_header(skb, type);
	if (!hdr)
		return 0;
	}

	if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
		return 0;
	msgtype = ptp_get_msgtype(hdr, type);

	if (unlikely(type & PTP_CLASS_V1))
		msgtype = data + offset + OFF_PTP_CONTROL;
	else
		msgtype = data + offset;
	if (rxts->msgtype != (*msgtype & 0xf))
	if (rxts->msgtype != (msgtype & 0xf))
		return 0;

	seqid = (__be16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
	if (rxts->seqid != ntohs(*seqid))
	seqid = be16_to_cpu(hdr->sequence_id);
	if (rxts->seqid != seqid)
		return 0;

	hash = ether_crc(DP83640_PACKET_HASH_LEN,
			 data + offset + DP83640_PACKET_HASH_OFFSET) >> 20;
			 (unsigned char *)&hdr->source_port_identity) >> 20;
	if (rxts->hash != hash)
		return 0;

@@ -982,35 +963,16 @@ static void decode_status_frame(struct dp83640_private *dp83640,

static int is_sync(struct sk_buff *skb, int type)
{
	u8 *data = skb->data, *msgtype;
	unsigned int offset = 0;

	if (type & PTP_CLASS_VLAN)
		offset += VLAN_HLEN;

	switch (type & PTP_CLASS_PMASK) {
	case PTP_CLASS_IPV4:
		offset += ETH_HLEN + IPV4_HLEN(data + offset) + UDP_HLEN;
		break;
	case PTP_CLASS_IPV6:
		offset += ETH_HLEN + IP6_HLEN + UDP_HLEN;
		break;
	case PTP_CLASS_L2:
		offset += ETH_HLEN;
		break;
	default:
		return 0;
	}

	if (type & PTP_CLASS_V1)
		offset += OFF_PTP_CONTROL;
	struct ptp_header *hdr;
	u8 msgtype;

	if (skb->len < offset + 1)
	hdr = ptp_parse_header(skb, type);
	if (!hdr)
		return 0;

	msgtype = data + offset;
	msgtype = ptp_get_msgtype(hdr, type);

	return (*msgtype & 0xf) == 0;
	return (msgtype & 0xf) == 0;
}

static void dp83640_free_clocks(void)
Loading