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.
387 lines
14 KiB
387 lines
14 KiB
From 15dae649ec3e0bbdb786037f50425d7f58ec8631 Mon Sep 17 00:00:00 2001
|
|
From: Igor Russkikh <irusskik@redhat.com>
|
|
Date: Fri, 6 Nov 2020 18:36:42 -0500
|
|
Subject: [PATCH 025/139] [netdrv] net: aquantia: rx filters for ptp
|
|
|
|
Message-id: <1604687916-15087-26-git-send-email-irusskik@redhat.com>
|
|
Patchwork-id: 338446
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.4 BZ 1857861 025/139] net: aquantia: rx filters for ptp
|
|
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 5a1bf9ef51cfd9bbe12a5a03a12a47eeacc0ef64
|
|
Author: Dmitry Bezrukov <dmitry.bezrukov@aquantia.com>
|
|
Date: Tue Oct 22 09:53:38 2019 +0000
|
|
|
|
net: aquantia: rx filters for ptp
|
|
|
|
We implement HW filter reservation for PTP traffic. Special location
|
|
in filters table is marked as reserved, because incoming ptp traffic
|
|
should be directed only to PTP designated queue. This way HW will do PTP
|
|
timestamping and proper processing.
|
|
|
|
Co-developed-by: Egor Pomozov <epomozov@marvell.com>
|
|
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>
|
|
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>
|
|
---
|
|
.../net/ethernet/aquantia/atlantic/aq_filters.c | 17 ++--
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 44 +++++++++++
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 8 +-
|
|
drivers/net/ethernet/aquantia/atlantic/aq_ptp.c | 14 ++++
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 12 ++-
|
|
.../aquantia/atlantic/hw_atl/hw_atl_llh_internal.h | 90 +++++++++++-----------
|
|
6 files changed, 131 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
|
|
index aee827f07c16..6102251bb909 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_filters.c
|
|
@@ -1,5 +1,5 @@
|
|
// SPDX-License-Identifier: GPL-2.0-only
|
|
-/* Copyright (C) 2014-2017 aQuantia Corporation. */
|
|
+/* Copyright (C) 2014-2019 aQuantia Corporation. */
|
|
|
|
/* File aq_filters.c: RX filters related functions. */
|
|
|
|
@@ -89,12 +89,14 @@ static int aq_check_approve_fl3l4(struct aq_nic_s *aq_nic,
|
|
struct aq_hw_rx_fltrs_s *rx_fltrs,
|
|
struct ethtool_rx_flow_spec *fsp)
|
|
{
|
|
+ u32 last_location = AQ_RX_LAST_LOC_FL3L4 -
|
|
+ aq_nic->aq_hw_rx_fltrs.fl3l4.reserved_count;
|
|
+
|
|
if (fsp->location < AQ_RX_FIRST_LOC_FL3L4 ||
|
|
- fsp->location > AQ_RX_LAST_LOC_FL3L4) {
|
|
+ fsp->location > last_location) {
|
|
netdev_err(aq_nic->ndev,
|
|
"ethtool: location must be in range [%d, %d]",
|
|
- AQ_RX_FIRST_LOC_FL3L4,
|
|
- AQ_RX_LAST_LOC_FL3L4);
|
|
+ AQ_RX_FIRST_LOC_FL3L4, last_location);
|
|
return -EINVAL;
|
|
}
|
|
if (rx_fltrs->fl3l4.is_ipv6 && rx_fltrs->fl3l4.active_ipv4) {
|
|
@@ -124,12 +126,15 @@ aq_check_approve_fl2(struct aq_nic_s *aq_nic,
|
|
struct aq_hw_rx_fltrs_s *rx_fltrs,
|
|
struct ethtool_rx_flow_spec *fsp)
|
|
{
|
|
+ u32 last_location = AQ_RX_LAST_LOC_FETHERT -
|
|
+ aq_nic->aq_hw_rx_fltrs.fet_reserved_count;
|
|
+
|
|
if (fsp->location < AQ_RX_FIRST_LOC_FETHERT ||
|
|
- fsp->location > AQ_RX_LAST_LOC_FETHERT) {
|
|
+ fsp->location > last_location) {
|
|
netdev_err(aq_nic->ndev,
|
|
"ethtool: location must be in range [%d, %d]",
|
|
AQ_RX_FIRST_LOC_FETHERT,
|
|
- AQ_RX_LAST_LOC_FETHERT);
|
|
+ last_location);
|
|
return -EINVAL;
|
|
}
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index 65384f45805f..22e4a5587c15 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -13,6 +13,7 @@
|
|
#include "aq_pci_func.h"
|
|
#include "aq_main.h"
|
|
#include "aq_ptp.h"
|
|
+#include "aq_filters.h"
|
|
|
|
#include <linux/moduleparam.h>
|
|
#include <linux/netdevice.h>
|
|
@@ -1105,3 +1106,46 @@ void aq_nic_shutdown(struct aq_nic_s *self)
|
|
err_exit:
|
|
rtnl_unlock();
|
|
}
|
|
+
|
|
+u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type)
|
|
+{
|
|
+ u8 location = 0xFF;
|
|
+ u32 fltr_cnt;
|
|
+ u32 n_bit;
|
|
+
|
|
+ switch (type) {
|
|
+ case aq_rx_filter_ethertype:
|
|
+ location = AQ_RX_LAST_LOC_FETHERT - AQ_RX_FIRST_LOC_FETHERT -
|
|
+ self->aq_hw_rx_fltrs.fet_reserved_count;
|
|
+ self->aq_hw_rx_fltrs.fet_reserved_count++;
|
|
+ break;
|
|
+ case aq_rx_filter_l3l4:
|
|
+ fltr_cnt = AQ_RX_LAST_LOC_FL3L4 - AQ_RX_FIRST_LOC_FL3L4;
|
|
+ n_bit = fltr_cnt - self->aq_hw_rx_fltrs.fl3l4.reserved_count;
|
|
+
|
|
+ self->aq_hw_rx_fltrs.fl3l4.active_ipv4 |= BIT(n_bit);
|
|
+ self->aq_hw_rx_fltrs.fl3l4.reserved_count++;
|
|
+ location = n_bit;
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return location;
|
|
+}
|
|
+
|
|
+void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type,
|
|
+ u32 location)
|
|
+{
|
|
+ switch (type) {
|
|
+ case aq_rx_filter_ethertype:
|
|
+ self->aq_hw_rx_fltrs.fet_reserved_count--;
|
|
+ break;
|
|
+ case aq_rx_filter_l3l4:
|
|
+ self->aq_hw_rx_fltrs.fl3l4.reserved_count--;
|
|
+ self->aq_hw_rx_fltrs.fl3l4.active_ipv4 &= ~BIT(location);
|
|
+ break;
|
|
+ default:
|
|
+ break;
|
|
+ }
|
|
+}
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
index 576432adda4c..c2513b79b9e9 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
@@ -18,6 +18,7 @@ struct aq_hw_ops;
|
|
struct aq_fw_s;
|
|
struct aq_vec_s;
|
|
struct aq_ptp_s;
|
|
+enum aq_rx_filter_type;
|
|
|
|
struct aq_nic_cfg_s {
|
|
const struct aq_hw_caps_s *aq_hw_caps;
|
|
@@ -72,6 +73,7 @@ struct aq_hw_rx_fl3l4 {
|
|
u8 active_ipv4;
|
|
u8 active_ipv6:2;
|
|
u8 is_ipv6;
|
|
+ u8 reserved_count;
|
|
};
|
|
|
|
struct aq_hw_rx_fltrs_s {
|
|
@@ -79,6 +81,8 @@ struct aq_hw_rx_fltrs_s {
|
|
u16 active_filters;
|
|
struct aq_hw_rx_fl2 fl2;
|
|
struct aq_hw_rx_fl3l4 fl3l4;
|
|
+ /*filter ether type */
|
|
+ u8 fet_reserved_count;
|
|
};
|
|
|
|
struct aq_nic_s {
|
|
@@ -154,5 +158,7 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self);
|
|
int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg);
|
|
int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self);
|
|
void aq_nic_shutdown(struct aq_nic_s *self);
|
|
-
|
|
+u8 aq_nic_reserve_filter(struct aq_nic_s *self, enum aq_rx_filter_type type);
|
|
+void aq_nic_release_filter(struct aq_nic_s *self, enum aq_rx_filter_type type,
|
|
+ u32 location);
|
|
#endif /* AQ_NIC_H */
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
index fbb1912a34d7..82409cb1f815 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ptp.c
|
|
@@ -8,12 +8,14 @@
|
|
*/
|
|
|
|
#include <linux/ptp_clock_kernel.h>
|
|
+#include <linux/ptp_classify.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/clocksource.h>
|
|
|
|
#include "aq_nic.h"
|
|
#include "aq_ptp.h"
|
|
#include "aq_ring.h"
|
|
+#include "aq_filters.h"
|
|
|
|
#define AQ_PTP_TX_TIMEOUT (HZ * 10)
|
|
|
|
@@ -62,6 +64,9 @@ struct aq_ptp_s {
|
|
struct aq_ring_s hwts_rx;
|
|
|
|
struct ptp_skb_ring skb_ring;
|
|
+
|
|
+ struct aq_rx_filter_l3l4 udp_filter;
|
|
+ struct aq_rx_filter_l2 eth_type_filter;
|
|
};
|
|
|
|
struct ptp_tm_offset {
|
|
@@ -933,6 +938,11 @@ int aq_ptp_init(struct aq_nic_s *aq_nic, unsigned int idx_vec)
|
|
aq_ptp_clock_init(aq_nic);
|
|
mutex_unlock(&aq_nic->fwreq_mutex);
|
|
|
|
+ aq_ptp->eth_type_filter.location =
|
|
+ aq_nic_reserve_filter(aq_nic, aq_rx_filter_ethertype);
|
|
+ aq_ptp->udp_filter.location =
|
|
+ aq_nic_reserve_filter(aq_nic, aq_rx_filter_l3l4);
|
|
+
|
|
return 0;
|
|
|
|
err_exit:
|
|
@@ -958,6 +968,10 @@ void aq_ptp_free(struct aq_nic_s *aq_nic)
|
|
if (!aq_ptp)
|
|
return;
|
|
|
|
+ aq_nic_release_filter(aq_nic, aq_rx_filter_ethertype,
|
|
+ aq_ptp->eth_type_filter.location);
|
|
+ aq_nic_release_filter(aq_nic, aq_rx_filter_l3l4,
|
|
+ aq_ptp->udp_filter.location);
|
|
/* disable ptp */
|
|
mutex_lock(&aq_nic->fwreq_mutex);
|
|
aq_nic->aq_fw_ops->enable_ptp(aq_nic->aq_hw, 0);
|
|
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 bd9e5a598657..56cec2ea0af0 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
|
|
@@ -1261,7 +1261,8 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self,
|
|
|
|
hw_atl_b0_hw_fl3l4_clear(self, data);
|
|
|
|
- if (data->cmd) {
|
|
+ if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_ADDR_L3 |
|
|
+ HW_ATL_RX_ENABLE_CMP_SRC_ADDR_L3)) {
|
|
if (!data->is_ipv6) {
|
|
hw_atl_rpfl3l4_ipv4_dest_addr_set(self,
|
|
location,
|
|
@@ -1278,8 +1279,13 @@ static int hw_atl_b0_hw_fl3l4_set(struct aq_hw_s *self,
|
|
data->ip_src);
|
|
}
|
|
}
|
|
- hw_atl_rpf_l4_dpd_set(self, data->p_dst, location);
|
|
- hw_atl_rpf_l4_spd_set(self, data->p_src, location);
|
|
+
|
|
+ if (data->cmd & (HW_ATL_RX_ENABLE_CMP_DEST_PORT_L4 |
|
|
+ HW_ATL_RX_ENABLE_CMP_SRC_PORT_L4)) {
|
|
+ hw_atl_rpf_l4_dpd_set(self, data->p_dst, location);
|
|
+ hw_atl_rpf_l4_spd_set(self, data->p_src, location);
|
|
+ }
|
|
+
|
|
hw_atl_rpfl3l4_cmd_set(self, location, data->cmd);
|
|
|
|
return aq_hw_err_from_flags(self);
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
|
|
index 65fb74a4d5ea..86c2d12b0dcd 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h
|
|
@@ -1308,6 +1308,52 @@
|
|
/* default value of bitfield et_val{f}[f:0] */
|
|
#define HW_ATL_RPF_ET_VALF_DEFAULT 0x0
|
|
|
|
+/* RX l3_l4_en{F} Bitfield Definitions
|
|
+ * Preprocessor definitions for the bitfield "l3_l4_en{F}".
|
|
+ * Parameter: filter {F} | stride size 0x4 | range [0, 7]
|
|
+ * PORT="pif_rpf_l3_l4_en_i[0]"
|
|
+ */
|
|
+
|
|
+#define HW_ATL_RPF_L3_REG_CTRL_ADR(filter) (0x00005380 + (filter) * 0x4)
|
|
+
|
|
+/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions
|
|
+ * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]".
|
|
+ * Parameter: location {D} | stride size 0x4 | range [0, 7]
|
|
+ * PORT="pif_rpf_l3_sa0_i[31:0]"
|
|
+ */
|
|
+
|
|
+/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_ADR(filter) (0x000053B0 + (filter) * 0x4)
|
|
+/* Bitmask for bitfield l3_sa0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu
|
|
+/* Inverted bitmask for bitfield l3_sa0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu
|
|
+/* Lower bit position of bitfield l3_sa0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_SHIFT 0
|
|
+/* Width of bitfield l3_sa0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_WIDTH 32
|
|
+/* Default value of bitfield l3_sa0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0
|
|
+
|
|
+/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions
|
|
+ * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]".
|
|
+ * Parameter: location {D} | stride size 0x4 | range [0, 7]
|
|
+ * PORT="pif_rpf_l3_da0_i[31:0]"
|
|
+ */
|
|
+
|
|
+ /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_ADR(filter) (0x000053B0 + (filter) * 0x4)
|
|
+/* Bitmask for bitfield l3_da0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu
|
|
+/* Inverted bitmask for bitfield l3_da0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu
|
|
+/* Lower bit position of bitfield l3_da0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_SHIFT 0
|
|
+/* Width of bitfield l3_da0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_WIDTH 32
|
|
+/* Default value of bitfield l3_da0[1F:0] */
|
|
+#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0
|
|
+
|
|
/* RX l4_sp{D}[F:0] Bitfield Definitions
|
|
* Preprocessor definitions for the bitfield "l4_sp{D}[F:0]".
|
|
* Parameter: srcport {D} | stride size 0x4 | range [0, 7]
|
|
@@ -2548,50 +2594,6 @@
|
|
/* default value of bitfield uP Force Interrupt */
|
|
#define HW_ATL_MCP_UP_FORCE_INTERRUPT_DEFAULT 0x0
|
|
|
|
-#define HW_ATL_RX_CTRL_ADDR_BEGIN_FL3L4 0x00005380
|
|
-#define HW_ATL_RX_SRCA_ADDR_BEGIN_FL3L4 0x000053B0
|
|
-#define HW_ATL_RX_DESTA_ADDR_BEGIN_FL3L4 0x000053D0
|
|
-
|
|
-#define HW_ATL_RPF_L3_REG_CTRL_ADR(location) (0x00005380 + (location) * 0x4)
|
|
-
|
|
-/* RX rpf_l3_sa{D}[1F:0] Bitfield Definitions
|
|
- * Preprocessor definitions for the bitfield "l3_sa{D}[1F:0]".
|
|
- * Parameter: location {D} | stride size 0x4 | range [0, 7]
|
|
- * PORT="pif_rpf_l3_sa0_i[31:0]"
|
|
- */
|
|
-
|
|
-/* Register address for bitfield pif_rpf_l3_sa0_i[31:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_ADR(location) (0x000053B0 + (location) * 0x4)
|
|
-/* Bitmask for bitfield l3_sa0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_MSK 0xFFFFFFFFu
|
|
-/* Inverted bitmask for bitfield l3_sa0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_MSKN 0xFFFFFFFFu
|
|
-/* Lower bit position of bitfield l3_sa0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_SHIFT 0
|
|
-/* Width of bitfield l3_sa0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_WIDTH 32
|
|
-/* Default value of bitfield l3_sa0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_SRCA_DEFAULT 0x0
|
|
-
|
|
-/* RX rpf_l3_da{D}[1F:0] Bitfield Definitions
|
|
- * Preprocessor definitions for the bitfield "l3_da{D}[1F:0]".
|
|
- * Parameter: location {D} | stride size 0x4 | range [0, 7]
|
|
- * PORT="pif_rpf_l3_da0_i[31:0]"
|
|
- */
|
|
-
|
|
- /* Register address for bitfield pif_rpf_l3_da0_i[31:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_ADR(location) (0x000053B0 + (location) * 0x4)
|
|
-/* Bitmask for bitfield l3_da0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_MSK 0xFFFFFFFFu
|
|
-/* Inverted bitmask for bitfield l3_da0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_MSKN 0xFFFFFFFFu
|
|
-/* Lower bit position of bitfield l3_da0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_SHIFT 0
|
|
-/* Width of bitfield l3_da0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_WIDTH 32
|
|
-/* Default value of bitfield l3_da0[1F:0] */
|
|
-#define HW_ATL_RPF_L3_DSTA_DEFAULT 0x0
|
|
-
|
|
#define HW_ATL_FW_SM_RAM 0x2U
|
|
|
|
#endif /* HW_ATL_LLH_INTERNAL_H */
|
|
--
|
|
2.13.6
|
|
|