Commit 04a18399 authored by Egor Pomozov's avatar Egor Pomozov Committed by David S. Miller
Browse files

net: aquantia: implement data PTP datapath



Here we do alloc/free IRQs for PTP rings.
We also implement processing of PTP packets on TX and RX sides.

Signed-off-by: default avatarEgor Pomozov <epomozov@marvell.com>
Co-developed-by: default avatarSergey Samoilenko <sergey.samoilenko@aquantia.com>
Signed-off-by: default avatarSergey Samoilenko <sergey.samoilenko@aquantia.com>
Co-developed-by: default avatarDmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: default avatarDmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 61cc502e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * aQuantia Corporation Network Driver
 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
 * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
 */

/* File aq_cfg.h: Definition of configuration parameters and constants. */
@@ -27,7 +27,7 @@

#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2)

#define AQ_CFG_IRQ_MASK                      0x1FFU
#define AQ_CFG_IRQ_MASK                      0x3FFU

#define AQ_CFG_VECS_MAX   8U
#define AQ_CFG_TCS_MAX    8U
+12 −0
Original line number Diff line number Diff line
@@ -244,6 +244,12 @@ struct aq_hw_ops {

	int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);

	int (*hw_ring_hwts_rx_fill)(struct aq_hw_s *self,
				    struct aq_ring_s *aq_ring);

	int (*hw_ring_hwts_rx_receive)(struct aq_hw_s *self,
				       struct aq_ring_s *ring);

	void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp);

	int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta);
@@ -252,6 +258,12 @@ struct aq_hw_ops {

	int (*hw_set_sys_clock)(struct aq_hw_s *self, u64 time, u64 ts);

	u16 (*rx_extract_ts)(struct aq_hw_s *self, u8 *p, unsigned int len,
			     u64 *timestamp);

	int (*extract_hwts)(struct aq_hw_s *self, u8 *p, unsigned int len,
			    u64 *timestamp);

	int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);
};

+22 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * aQuantia Corporation Network Driver
 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
 * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
 */

/* File aq_main.c: Main file for aQuantia Linux driver. */
@@ -10,10 +10,13 @@
#include "aq_nic.h"
#include "aq_pci_func.h"
#include "aq_ethtool.h"
#include "aq_ptp.h"
#include "aq_filters.h"

#include <linux/netdevice.h>
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/udp.h>

MODULE_LICENSE("GPL v2");
MODULE_VERSION(AQ_CFG_DRV_VERSION);
@@ -93,6 +96,24 @@ static int aq_ndev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
	struct aq_nic_s *aq_nic = netdev_priv(ndev);

	if (unlikely(aq_utils_obj_test(&aq_nic->flags, AQ_NIC_PTP_DPATH_UP))) {
		/* Hardware adds the Timestamp for PTPv2 802.AS1
		 * and PTPv2 IPv4 UDP.
		 * We have to push even general 320 port messages to the ptp
		 * queue explicitly. This is a limitation of current firmware
		 * and hardware PTP design of the chip. Otherwise ptp stream
		 * will fail to sync
		 */
		if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ||
		    unlikely((ip_hdr(skb)->version == 4) &&
			     (ip_hdr(skb)->protocol == IPPROTO_UDP) &&
			     ((udp_hdr(skb)->dest == htons(319)) ||
			      (udp_hdr(skb)->dest == htons(320)))) ||
		    unlikely(eth_hdr(skb)->h_proto == htons(ETH_P_1588)))
			return aq_ptp_xmit(aq_nic, skb);
	}

	skb_tx_timestamp(skb);
	return aq_nic_xmit(aq_nic, skb);
}

+14 −4
Original line number Diff line number Diff line
@@ -146,8 +146,11 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
			self->aq_hw->aq_link_status.mbps);
		aq_nic_update_interrupt_moderation_settings(self);

		if (self->aq_ptp)
		if (self->aq_ptp) {
			aq_ptp_clock_init(self);
			aq_ptp_tm_offset_set(self,
					     self->aq_hw->aq_link_status.mbps);
		}

		/* Driver has to update flow control settings on RX block
		 * on any link event.
@@ -196,6 +199,8 @@ static void aq_nic_service_task(struct work_struct *work)
					     service_task);
	int err;

	aq_ptp_service_task(self);

	if (aq_utils_obj_test(&self->flags, AQ_NIC_FLAGS_IS_NOT_READY))
		return;

@@ -408,6 +413,10 @@ int aq_nic_start(struct aq_nic_s *self)
				goto err_exit;
		}

		err = aq_ptp_irq_alloc(self);
		if (err < 0)
			goto err_exit;

		if (self->aq_nic_cfg.link_irq_vec) {
			int irqvec = pci_irq_vector(self->pdev,
						   self->aq_nic_cfg.link_irq_vec);
@@ -440,8 +449,7 @@ err_exit:
	return err;
}

static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
				   struct sk_buff *skb,
unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
			    struct aq_ring_s *ring)
{
	unsigned int ret = 0U;
@@ -973,6 +981,8 @@ int aq_nic_stop(struct aq_nic_s *self)
	else
		aq_pci_func_free_irqs(self);

	aq_ptp_irq_free(self);

	for (i = 0U, aq_vec = self->aq_vec[0];
		self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
		aq_vec_stop(aq_vec);
+3 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ struct aq_nic_cfg_s {
#define AQ_NIC_FLAG_STOPPING    0x00000008U
#define AQ_NIC_FLAG_RESETTING   0x00000010U
#define AQ_NIC_FLAG_CLOSING     0x00000020U
#define AQ_NIC_PTP_DPATH_UP     0x02000000U
#define AQ_NIC_LINK_DOWN        0x04000000U
#define AQ_NIC_FLAG_ERR_UNPLUG  0x40000000U
#define AQ_NIC_FLAG_ERR_HW      0x80000000U
@@ -129,6 +130,8 @@ void aq_nic_cfg_start(struct aq_nic_s *self);
int aq_nic_ndev_register(struct aq_nic_s *self);
void aq_nic_ndev_free(struct aq_nic_s *self);
int aq_nic_start(struct aq_nic_s *self);
unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
			    struct aq_ring_s *ring);
int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb);
int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p);
int aq_nic_get_regs_count(struct aq_nic_s *self);
Loading