Skip to content

Commit

Permalink
net: aquantia: implement data PTP datapath
Browse files Browse the repository at this point in the history
Here we do alloc/free IRQs for PTP rings.
We also implement processing of PTP packets on TX and RX sides.

Signed-off-by: Egor Pomozov <epomozov@marvell.com>
Co-developed-by: Sergey Samoilenko <sergey.samoilenko@aquantia.com>
Signed-off-by: Sergey Samoilenko <sergey.samoilenko@aquantia.com>
Co-developed-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Egor Pomozov authored and David S. Miller committed Oct 24, 2019
1 parent 61cc502 commit 04a1839
Show file tree
Hide file tree
Showing 11 changed files with 738 additions and 12 deletions.
4 changes: 2 additions & 2 deletions drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* 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. */
Expand All @@ -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
Expand Down
12 changes: 12 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
};

Expand Down
23 changes: 22 additions & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_main.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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. */
Expand All @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down
18 changes: 14 additions & 4 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -440,9 +449,8 @@ int aq_nic_start(struct aq_nic_s *self)
return err;
}

static unsigned int aq_nic_map_skb(struct aq_nic_s *self,
struct sk_buff *skb,
struct aq_ring_s *ring)
unsigned int aq_nic_map_skb(struct aq_nic_s *self, struct sk_buff *skb,
struct aq_ring_s *ring)
{
unsigned int ret = 0U;
unsigned int nr_frags = skb_shinfo(skb)->nr_frags;
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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_pci_func.c: Definition of PCI functions. */
Expand Down Expand Up @@ -269,6 +269,9 @@ static int aq_pci_probe(struct pci_dev *pdev,
numvecs = min((u8)AQ_CFG_VECS_DEF,
aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs);
numvecs = min(numvecs, num_online_cpus());
/* Request IRQ vector for PTP */
numvecs += 1;

numvecs += AQ_HW_SERVICE_IRQS;
/*enable interrupts */
#if !AQ_CFG_FORCE_LEGACY_INT
Expand Down
Loading

0 comments on commit 04a1839

Please sign in to comment.