You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
674 lines
21 KiB
674 lines
21 KiB
From b7d9cef8662d722c6256955eaa85d0ef25cfbe1e Mon Sep 17 00:00:00 2001
|
|
From: Igor Russkikh <irusskik@redhat.com>
|
|
Date: Fri, 6 Nov 2020 18:36:39 -0500
|
|
Subject: [PATCH 022/139] [netdrv] net: aquantia: add PTP rings infrastructure
|
|
|
|
Message-id: <1604687916-15087-23-git-send-email-irusskik@redhat.com>
|
|
Patchwork-id: 338454
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.4 BZ 1857861 022/139] net: aquantia: add PTP rings infrastructure
|
|
Bugzilla: 1857861
|
|
RH-Acked-by: David Arcari <darcari@redhat.com>
|
|
RH-Acked-by: John Linville <linville@redhat.com>
|
|
RH-Acked-by: Tony Camuso <tcamuso@redhat.com>
|
|
|
|
Bugzilla: http://bugzilla.redhat.com/1857861
|
|
|
|
commit 94ad94558b0fbf18dd6fb0987540af1693157556
|
|
Author: Egor Pomozov <epomozov@marvell.com>
|
|
Date: Tue Oct 22 09:53:29 2019 +0000
|
|
|
|
net: aquantia: add PTP rings infrastructure
|
|
|
|
Add implementations of PTP rings alloc/free.
|
|
|
|
PTP desing on this device uses two separate rings on a separate traffic
|
|
class for traffic rx/tx.
|
|
|
|
Third ring (hwts) is not a traffic ring, but is used only to receive timestamps
|
|
of the transmitted packets.
|
|
|
|
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>
|
|
|
|
Signed-off-by: Igor Russkikh <irusskik@redhat.com>
|
|
|
|
Cc: David Arcari <darcari@redhat.com>
|
|
Cc: Igor Russkikh <irusskik@redhat.com>
|
|
Signed-off-by: Jan Stancek <jstancek@redhat.com>
|
|
---
|
|
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 4 +
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 16 ++
|
|
drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 235 +++++++++++++++++++++
|
|
drivers/net/ethernet/aquantia/atlantic/aq_ptp.h | 8 +
|
|
drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 26 ++-
|
|
drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 6 +-
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 45 +++-
|
|
.../aquantia/atlantic/hw_atl/hw_atl_b0_internal.h | 9 +-
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c | 14 ++
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h | 6 +
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils.h | 8 +
|
|
11 files changed, 365 insertions(+), 12 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
index cd6fc075bb2c..fa943852757e 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
@@ -240,6 +240,10 @@ struct aq_hw_ops {
|
|
int (*hw_set_offload)(struct aq_hw_s *self,
|
|
struct aq_nic_cfg_s *aq_nic_cfg);
|
|
|
|
+ int (*hw_tx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
|
|
+
|
|
+ int (*hw_rx_tc_mode_get)(struct aq_hw_s *self, u32 *tc_mode);
|
|
+
|
|
void (*hw_get_ptp_ts)(struct aq_hw_s *self, u64 *stamp);
|
|
|
|
int (*hw_adj_clock_freq)(struct aq_hw_s *self, s32 delta);
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index dc9769fe762b..ecca2c4cf140 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -339,6 +339,14 @@ int aq_nic_init(struct aq_nic_s *self)
|
|
if (err < 0)
|
|
goto err_exit;
|
|
|
|
+ err = aq_ptp_ring_alloc(self);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+ err = aq_ptp_ring_init(self);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
netif_carrier_off(self->ndev);
|
|
|
|
err_exit:
|
|
@@ -369,6 +377,10 @@ int aq_nic_start(struct aq_nic_s *self)
|
|
goto err_exit;
|
|
}
|
|
|
|
+ err = aq_ptp_ring_start(self);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
err = self->aq_hw_ops->hw_start(self->aq_hw);
|
|
if (err < 0)
|
|
goto err_exit;
|
|
@@ -965,6 +977,8 @@ int aq_nic_stop(struct aq_nic_s *self)
|
|
self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i])
|
|
aq_vec_stop(aq_vec);
|
|
|
|
+ aq_ptp_ring_stop(self);
|
|
+
|
|
return self->aq_hw_ops->hw_stop(self->aq_hw);
|
|
}
|
|
|
|
@@ -981,6 +995,8 @@ void aq_nic_deinit(struct aq_nic_s *self)
|
|
aq_vec_deinit(aq_vec);
|
|
|
|
aq_ptp_unregister(self);
|
|
+ aq_ptp_ring_deinit(self);
|
|
+ aq_ptp_ring_free(self);
|
|
aq_ptp_free(self);
|
|
|
|
if (likely(self->aq_fw_ops->deinit)) {
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
index 02c2a8cd1219..f2fd0ca14a49 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
@@ -12,14 +12,55 @@
|
|
|
|
#include "aq_nic.h"
|
|
#include "aq_ptp.h"
|
|
+#include "aq_ring.h"
|
|
+
|
|
+struct ptp_skb_ring {
|
|
+ struct sk_buff **buff;
|
|
+ spinlock_t lock;
|
|
+ unsigned int size;
|
|
+ unsigned int head;
|
|
+ unsigned int tail;
|
|
+};
|
|
|
|
struct aq_ptp_s {
|
|
struct aq_nic_s *aq_nic;
|
|
spinlock_t ptp_lock;
|
|
+ spinlock_t ptp_ring_lock;
|
|
struct ptp_clock *ptp_clock;
|
|
struct ptp_clock_info ptp_info;
|
|
+
|
|
+ struct aq_ring_param_s ptp_ring_param;
|
|
+
|
|
+ struct aq_ring_s ptp_tx;
|
|
+ struct aq_ring_s ptp_rx;
|
|
+ struct aq_ring_s hwts_rx;
|
|
+
|
|
+ struct ptp_skb_ring skb_ring;
|
|
};
|
|
|
|
+static int aq_ptp_skb_ring_init(struct ptp_skb_ring *ring, unsigned int size)
|
|
+{
|
|
+ struct sk_buff **buff = kmalloc(sizeof(*buff) * size, GFP_KERNEL);
|
|
+
|
|
+ if (!buff)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ spin_lock_init(&ring->lock);
|
|
+
|
|
+ ring->buff = buff;
|
|
+ ring->size = size;
|
|
+ ring->head = 0;
|
|
+ ring->tail = 0;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void aq_ptp_skb_ring_release(struct ptp_skb_ring *ring)
|
|
+{
|
|
+ kfree(ring->buff);
|
|
+ ring->buff = NULL;
|
|
+}
|
|
+
|
|
/* aq_ptp_adjfine
|
|
* @ptp: the ptp clock structure
|
|
* @ppb: parts per billion adjustment from base
|
|
@@ -107,6 +148,190 @@ static int aq_ptp_settime(struct ptp_clock_info *ptp,
|
|
return 0;
|
|
}
|
|
|
|
+int aq_ptp_ring_init(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+ int err = 0;
|
|
+
|
|
+ if (!aq_ptp)
|
|
+ return 0;
|
|
+
|
|
+ err = aq_ring_init(&aq_ptp->ptp_tx);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_tx_init(aq_nic->aq_hw,
|
|
+ &aq_ptp->ptp_tx,
|
|
+ &aq_ptp->ptp_ring_param);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+ err = aq_ring_init(&aq_ptp->ptp_rx);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
|
|
+ &aq_ptp->ptp_rx,
|
|
+ &aq_ptp->ptp_ring_param);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+ err = aq_ring_rx_fill(&aq_ptp->ptp_rx);
|
|
+ if (err < 0)
|
|
+ goto err_rx_free;
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_rx_fill(aq_nic->aq_hw,
|
|
+ &aq_ptp->ptp_rx,
|
|
+ 0U);
|
|
+ if (err < 0)
|
|
+ goto err_rx_free;
|
|
+
|
|
+ err = aq_ring_init(&aq_ptp->hwts_rx);
|
|
+ if (err < 0)
|
|
+ goto err_rx_free;
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_rx_init(aq_nic->aq_hw,
|
|
+ &aq_ptp->hwts_rx,
|
|
+ &aq_ptp->ptp_ring_param);
|
|
+
|
|
+ return err;
|
|
+
|
|
+err_rx_free:
|
|
+ aq_ring_rx_deinit(&aq_ptp->ptp_rx);
|
|
+err_exit:
|
|
+ return err;
|
|
+}
|
|
+
|
|
+int aq_ptp_ring_start(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+ int err = 0;
|
|
+
|
|
+ if (!aq_ptp)
|
|
+ return 0;
|
|
+
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_tx_start(aq_nic->aq_hw, &aq_ptp->ptp_tx);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw, &aq_ptp->ptp_rx);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+ err = aq_nic->aq_hw_ops->hw_ring_rx_start(aq_nic->aq_hw,
|
|
+ &aq_ptp->hwts_rx);
|
|
+ if (err < 0)
|
|
+ goto err_exit;
|
|
+
|
|
+err_exit:
|
|
+ return err;
|
|
+}
|
|
+
|
|
+void aq_ptp_ring_stop(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+
|
|
+ if (!aq_ptp)
|
|
+ return;
|
|
+
|
|
+ aq_nic->aq_hw_ops->hw_ring_tx_stop(aq_nic->aq_hw, &aq_ptp->ptp_tx);
|
|
+ aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->ptp_rx);
|
|
+
|
|
+ aq_nic->aq_hw_ops->hw_ring_rx_stop(aq_nic->aq_hw, &aq_ptp->hwts_rx);
|
|
+}
|
|
+
|
|
+void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+
|
|
+ if (!aq_ptp || !aq_ptp->ptp_tx.aq_nic || !aq_ptp->ptp_rx.aq_nic)
|
|
+ return;
|
|
+
|
|
+ aq_ring_tx_clean(&aq_ptp->ptp_tx);
|
|
+ aq_ring_rx_deinit(&aq_ptp->ptp_rx);
|
|
+}
|
|
+
|
|
+#define PTP_8TC_RING_IDX 8
|
|
+#define PTP_4TC_RING_IDX 16
|
|
+#define PTP_HWST_RING_IDX 31
|
|
+
|
|
+int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+ unsigned int tx_ring_idx, rx_ring_idx;
|
|
+ struct aq_ring_s *hwts = 0;
|
|
+ u32 tx_tc_mode, rx_tc_mode;
|
|
+ struct aq_ring_s *ring;
|
|
+ int err;
|
|
+
|
|
+ if (!aq_ptp)
|
|
+ return 0;
|
|
+
|
|
+ /* Index must to be 8 (8 TCs) or 16 (4 TCs).
|
|
+ * It depends from Traffic Class mode.
|
|
+ */
|
|
+ aq_nic->aq_hw_ops->hw_tx_tc_mode_get(aq_nic->aq_hw, &tx_tc_mode);
|
|
+ if (tx_tc_mode == 0)
|
|
+ tx_ring_idx = PTP_8TC_RING_IDX;
|
|
+ else
|
|
+ tx_ring_idx = PTP_4TC_RING_IDX;
|
|
+
|
|
+ ring = aq_ring_tx_alloc(&aq_ptp->ptp_tx, aq_nic,
|
|
+ tx_ring_idx, &aq_nic->aq_nic_cfg);
|
|
+ if (!ring) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_exit;
|
|
+ }
|
|
+
|
|
+ aq_nic->aq_hw_ops->hw_rx_tc_mode_get(aq_nic->aq_hw, &rx_tc_mode);
|
|
+ if (rx_tc_mode == 0)
|
|
+ rx_ring_idx = PTP_8TC_RING_IDX;
|
|
+ else
|
|
+ rx_ring_idx = PTP_4TC_RING_IDX;
|
|
+
|
|
+ ring = aq_ring_rx_alloc(&aq_ptp->ptp_rx, aq_nic,
|
|
+ rx_ring_idx, &aq_nic->aq_nic_cfg);
|
|
+ if (!ring) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_exit_ptp_tx;
|
|
+ }
|
|
+
|
|
+ hwts = aq_ring_hwts_rx_alloc(&aq_ptp->hwts_rx, aq_nic, PTP_HWST_RING_IDX,
|
|
+ aq_nic->aq_nic_cfg.rxds,
|
|
+ aq_nic->aq_nic_cfg.aq_hw_caps->rxd_size);
|
|
+ if (!hwts) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_exit_ptp_rx;
|
|
+ }
|
|
+
|
|
+ err = aq_ptp_skb_ring_init(&aq_ptp->skb_ring, aq_nic->aq_nic_cfg.rxds);
|
|
+ if (err != 0) {
|
|
+ err = -ENOMEM;
|
|
+ goto err_exit_hwts_rx;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+err_exit_hwts_rx:
|
|
+ aq_ring_free(&aq_ptp->hwts_rx);
|
|
+err_exit_ptp_rx:
|
|
+ aq_ring_free(&aq_ptp->ptp_rx);
|
|
+err_exit_ptp_tx:
|
|
+ aq_ring_free(&aq_ptp->ptp_tx);
|
|
+err_exit:
|
|
+ return err;
|
|
+}
|
|
+
|
|
+void aq_ptp_ring_free(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+
|
|
+ if (!aq_ptp)
|
|
+ return;
|
|
+
|
|
+ aq_ring_free(&aq_ptp->ptp_tx);
|
|
+ aq_ring_free(&aq_ptp->ptp_rx);
|
|
+ aq_ring_free(&aq_ptp->hwts_rx);
|
|
+
|
|
+ aq_ptp_skb_ring_release(&aq_ptp->skb_ring);
|
|
+}
|
|
+
|
|
static struct ptp_clock_info aq_ptp_clock = {
|
|
.owner = THIS_MODULE,
|
|
.name = "atlantic ptp",
|
|
@@ -122,6 +347,15 @@ static struct ptp_clock_info aq_ptp_clock = {
|
|
.pin_config = NULL,
|
|
};
|
|
|
|
+void aq_ptp_clock_init(struct aq_nic_s *aq_nic)
|
|
+{
|
|
+ struct aq_ptp_s *aq_ptp = aq_nic->aq_ptp;
|
|
+ struct timespec64 ts;
|
|
+
|
|
+ ktime_get_real_ts64(&ts);
|
|
+ aq_ptp_settime(&aq_ptp->ptp_info, &ts);
|
|
+}
|
|
+
|
|
int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|
{
|
|
struct hw_atl_utils_mbox mbox;
|
|
@@ -155,6 +389,7 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|
aq_ptp->aq_nic = aq_nic;
|
|
|
|
spin_lock_init(&aq_ptp->ptp_lock);
|
|
+ spin_lock_init(&aq_ptp->ptp_ring_lock);
|
|
|
|
aq_ptp->ptp_info = aq_ptp_clock;
|
|
clock = ptp_clock_register(&aq_ptp->ptp_info, &aq_nic->ndev->dev);
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h
|
|
index cea238959b20..32350f75e138 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.h
|
|
@@ -17,6 +17,14 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec);
|
|
void aq_ptp_unregister(struct aq_nic_s *aq_nic);
|
|
void aq_ptp_free(struct aq_nic_s *aq_nic);
|
|
|
|
+int aq_ptp_ring_alloc(struct aq_nic_s *aq_nic);
|
|
+void aq_ptp_ring_free(struct aq_nic_s *aq_nic);
|
|
+
|
|
+int aq_ptp_ring_init(struct aq_nic_s *aq_nic);
|
|
+int aq_ptp_ring_start(struct aq_nic_s *aq_nic);
|
|
+void aq_ptp_ring_stop(struct aq_nic_s *aq_nic);
|
|
+void aq_ptp_ring_deinit(struct aq_nic_s *aq_nic);
|
|
+
|
|
void aq_ptp_clock_init(struct aq_nic_s *aq_nic);
|
|
|
|
#endif /* AQ_PTP_H */
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
|
|
index 76bdbe1596d6..8e84ff6eefe3 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
|
|
@@ -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_ring.c: Definition of functions for Rx/Tx rings. */
|
|
@@ -177,6 +177,30 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self,
|
|
return self;
|
|
}
|
|
|
|
+struct aq_ring_s *
|
|
+aq_ring_hwts_rx_alloc(struct aq_ring_s *self, struct aq_nic_s *aq_nic,
|
|
+ unsigned int idx, unsigned int size, unsigned int dx_size)
|
|
+{
|
|
+ struct device *dev = aq_nic_get_dev(aq_nic);
|
|
+ size_t sz = size * dx_size + AQ_CFG_RXDS_DEF;
|
|
+
|
|
+ memset(self, 0, sizeof(*self));
|
|
+
|
|
+ self->aq_nic = aq_nic;
|
|
+ self->idx = idx;
|
|
+ self->size = size;
|
|
+ self->dx_size = dx_size;
|
|
+
|
|
+ self->dx_ring = dma_alloc_coherent(dev, sz, &self->dx_ring_pa,
|
|
+ GFP_KERNEL);
|
|
+ if (!self->dx_ring) {
|
|
+ aq_ring_free(self);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return self;
|
|
+}
|
|
+
|
|
int aq_ring_init(struct aq_ring_s *self)
|
|
{
|
|
self->hw_head = 0;
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
|
|
index 47abd09d06c2..068689f44bc9 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
|
|
@@ -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_ring.h: Declaration of functions for Rx/Tx rings. */
|
|
@@ -174,4 +174,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
|
|
int budget);
|
|
int aq_ring_rx_fill(struct aq_ring_s *self);
|
|
|
|
+struct aq_ring_s *aq_ring_hwts_rx_alloc(struct aq_ring_s *self,
|
|
+ struct aq_nic_s *aq_nic, unsigned int idx,
|
|
+ unsigned int size, unsigned int dx_size);
|
|
+
|
|
#endif /* AQ_RING_H */
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
|
|
index 881caa8ee319..55c7f9985692 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
|
|
@@ -126,13 +126,16 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
|
|
hw_atl_tps_tx_pkt_shed_desc_tc_arb_mode_set(self, 0U);
|
|
hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, 0U);
|
|
|
|
- hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, 0U);
|
|
- hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, 0U);
|
|
- hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, 0U);
|
|
- hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, 0U);
|
|
+ tc = 0;
|
|
+
|
|
+ /* TX Packet Scheduler Data TC0 */
|
|
+ hw_atl_tps_tx_pkt_shed_tc_data_max_credit_set(self, 0xFFF, tc);
|
|
+ hw_atl_tps_tx_pkt_shed_tc_data_weight_set(self, 0x64, tc);
|
|
+ hw_atl_tps_tx_pkt_shed_desc_tc_max_credit_set(self, 0x50, tc);
|
|
+ hw_atl_tps_tx_pkt_shed_desc_tc_weight_set(self, 0x1E, tc);
|
|
|
|
- /* Tx buf size */
|
|
- buff_size = HW_ATL_B0_TXBUF_MAX;
|
|
+ /* Tx buf size TC0 */
|
|
+ buff_size = HW_ATL_B0_TXBUF_MAX - HW_ATL_B0_PTP_TXBUF_SIZE;
|
|
|
|
hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, buff_size, tc);
|
|
hw_atl_tpb_tx_buff_hi_threshold_per_tc_set(self,
|
|
@@ -143,10 +146,15 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
|
|
(buff_size *
|
|
(1024 / 32U) * 50U) /
|
|
100U, tc);
|
|
+ /* Init TC2 for PTP_TX */
|
|
+ tc = 2;
|
|
+
|
|
+ hw_atl_tpb_tx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_TXBUF_SIZE,
|
|
+ tc);
|
|
|
|
/* QoS Rx buf size per TC */
|
|
tc = 0;
|
|
- buff_size = HW_ATL_B0_RXBUF_MAX;
|
|
+ buff_size = HW_ATL_B0_RXBUF_MAX - HW_ATL_B0_PTP_RXBUF_SIZE;
|
|
|
|
hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc);
|
|
hw_atl_rpb_rx_buff_hi_threshold_per_tc_set(self,
|
|
@@ -160,6 +168,14 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
|
|
|
|
hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc);
|
|
|
|
+ /* Init TC2 for PTP_RX */
|
|
+ tc = 2;
|
|
+
|
|
+ hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, HW_ATL_B0_PTP_RXBUF_SIZE,
|
|
+ tc);
|
|
+ /* No flow control for PTP */
|
|
+ hw_atl_rpb_rx_xoff_en_per_tc_set(self, 0U, tc);
|
|
+
|
|
/* QoS 802.1p priority -> TC mapping */
|
|
for (i_priority = 8U; i_priority--;)
|
|
hw_atl_rpf_rpb_user_priority_tc_map_set(self, i_priority, 0U);
|
|
@@ -1007,6 +1023,18 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self,
|
|
return aq_hw_err_from_flags(self);
|
|
}
|
|
|
|
+static int hw_atl_b0_tx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode)
|
|
+{
|
|
+ *tc_mode = hw_atl_rpb_tps_tx_tc_mode_get(self);
|
|
+ return aq_hw_err_from_flags(self);
|
|
+}
|
|
+
|
|
+static int hw_atl_b0_rx_tc_mode_get(struct aq_hw_s *self, u32 *tc_mode)
|
|
+{
|
|
+ *tc_mode = hw_atl_rpb_rpf_rx_traf_class_mode_get(self);
|
|
+ return aq_hw_err_from_flags(self);
|
|
+}
|
|
+
|
|
#define get_ptp_ts_val_u64(self, indx) \
|
|
((u64)(hw_atl_pcs_ptp_clock_get(self, indx) & 0xffff))
|
|
|
|
@@ -1278,6 +1306,9 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
|
|
.hw_get_hw_stats = hw_atl_utils_get_hw_stats,
|
|
.hw_get_fw_version = hw_atl_utils_get_fw_version,
|
|
|
|
+ .hw_tx_tc_mode_get = hw_atl_b0_tx_tc_mode_get,
|
|
+ .hw_rx_tc_mode_get = hw_atl_b0_rx_tc_mode_get,
|
|
+
|
|
.hw_get_ptp_ts = hw_atl_b0_get_ptp_ts,
|
|
.hw_adj_sys_clock = hw_atl_b0_adj_sys_clock,
|
|
.hw_set_sys_clock = hw_atl_b0_set_sys_clock,
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
|
|
index 808d8cd4252a..7ab23a1751d3 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h
|
|
@@ -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 hw_atl_b0_internal.h: Definition of Atlantic B0 chip specific
|
|
@@ -64,8 +64,11 @@
|
|
#define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU
|
|
#define HW_ATL_B0_MPI_SPEED_SHIFT 16U
|
|
|
|
-#define HW_ATL_B0_TXBUF_MAX 160U
|
|
-#define HW_ATL_B0_RXBUF_MAX 320U
|
|
+#define HW_ATL_B0_TXBUF_MAX 160U
|
|
+#define HW_ATL_B0_PTP_TXBUF_SIZE 8U
|
|
+
|
|
+#define HW_ATL_B0_RXBUF_MAX 320U
|
|
+#define HW_ATL_B0_PTP_RXBUF_SIZE 16U
|
|
|
|
#define HW_ATL_B0_RSS_REDIRECTION_MAX 64U
|
|
#define HW_ATL_B0_RSS_REDIRECTION_BITS 3U
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
|
|
index eb982288fc52..368b5caf3c49 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c
|
|
@@ -572,6 +572,13 @@ void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw,
|
|
rx_traf_class_mode);
|
|
}
|
|
|
|
+u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw)
|
|
+{
|
|
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_RPB_RPF_RX_TC_MODE_ADR,
|
|
+ HW_ATL_RPB_RPF_RX_TC_MODE_MSK,
|
|
+ HW_ATL_RPB_RPF_RX_TC_MODE_SHIFT);
|
|
+}
|
|
+
|
|
void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en)
|
|
{
|
|
aq_hw_write_reg_bit(aq_hw, HW_ATL_RPB_RX_BUF_EN_ADR,
|
|
@@ -1290,6 +1297,13 @@ void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en)
|
|
HW_ATL_TPB_TX_BUF_EN_SHIFT, tx_buff_en);
|
|
}
|
|
|
|
+u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw)
|
|
+{
|
|
+ return aq_hw_read_reg_bit(aq_hw, HW_ATL_TPB_TX_TC_MODE_ADDR,
|
|
+ HW_ATL_TPB_TX_TC_MODE_MSK,
|
|
+ HW_ATL_TPB_TX_TC_MODE_SHIFT);
|
|
+}
|
|
+
|
|
void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
|
|
u32 tx_traf_class_mode)
|
|
{
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
|
|
index 7753ab860c95..a579864b6ba1 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h
|
|
@@ -292,6 +292,9 @@ void hw_atl_rpb_dma_sys_lbk_set(struct aq_hw_s *aq_hw, u32 dma_sys_lbk);
|
|
void hw_atl_rpb_rpf_rx_traf_class_mode_set(struct aq_hw_s *aq_hw,
|
|
u32 rx_traf_class_mode);
|
|
|
|
+/* get rx traffic class mode */
|
|
+u32 hw_atl_rpb_rpf_rx_traf_class_mode_get(struct aq_hw_s *aq_hw);
|
|
+
|
|
/* set rx buffer enable */
|
|
void hw_atl_rpb_rx_buff_en_set(struct aq_hw_s *aq_hw, u32 rx_buff_en);
|
|
|
|
@@ -605,6 +608,9 @@ void hw_atl_thm_lso_tcp_flag_of_middle_pkt_set(struct aq_hw_s *aq_hw,
|
|
void hw_atl_rpb_tps_tx_tc_mode_set(struct aq_hw_s *aq_hw,
|
|
u32 tx_traf_class_mode);
|
|
|
|
+/* get TX Traffic Class Mode */
|
|
+u32 hw_atl_rpb_tps_tx_tc_mode_get(struct aq_hw_s *aq_hw);
|
|
+
|
|
/* set tx buffer enable */
|
|
void hw_atl_tpb_tx_buff_en_set(struct aq_hw_s *aq_hw, u32 tx_buff_en);
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
index f2eb94f298e2..77132bda4696 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h
|
|
@@ -44,6 +44,14 @@ struct __packed hw_atl_rxd_wb_s {
|
|
u16 vlan;
|
|
};
|
|
|
|
+/* Hardware rx HW TIMESTAMP writeback */
|
|
+struct __packed hw_atl_rxd_hwts_wb_s {
|
|
+ u32 sec_hw;
|
|
+ u32 ns;
|
|
+ u32 sec_lw0;
|
|
+ u32 sec_lw1;
|
|
+};
|
|
+
|
|
struct __packed hw_atl_stats_s {
|
|
u32 uprc;
|
|
u32 mprc;
|
|
--
|
|
2.13.6
|
|
|