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.
304 lines
11 KiB
304 lines
11 KiB
From b45b3f269983806665793a1f482c11ad8ae3cf91 Mon Sep 17 00:00:00 2001
|
|
From: Igor Russkikh <irusskik@redhat.com>
|
|
Date: Fri, 6 Nov 2020 18:37:05 -0500
|
|
Subject: [PATCH 048/139] [netdrv] net: atlantic: update flow control logic
|
|
|
|
Message-id: <1604687916-15087-49-git-send-email-irusskik@redhat.com>
|
|
Patchwork-id: 338475
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.4 BZ 1857861 048/139] net: atlantic: update flow control logic
|
|
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 8009bb1928a6d5b0ce2d8a1dba79972f01e50533
|
|
Author: Nikita Danilov <ndanilov@marvell.com>
|
|
Date: Thu Nov 7 22:42:04 2019 +0000
|
|
|
|
net: atlantic: update flow control logic
|
|
|
|
We now differentiate requested and negotiated flow control
|
|
modes. Therefore `ethtool -A` now operates on local requested
|
|
FC values, and regular link settings shows the negotiated FC
|
|
settings.
|
|
|
|
Signed-off-by: Nikita Danilov <ndanilov@marvell.com>
|
|
Signed-off-by: Igor Russkikh <irusskikh@marvell.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_cfg.h | 6 ---
|
|
.../net/ethernet/aquantia/atlantic/aq_ethtool.c | 10 ++---
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 19 +++++----
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.h | 14 ++++++-
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 2 +-
|
|
.../ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 2 +-
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 47 +++++++++++++---------
|
|
7 files changed, 59 insertions(+), 41 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
|
|
index d02b0d79f68a..f0c41f7408e5 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h
|
|
@@ -70,12 +70,6 @@
|
|
|
|
/*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/
|
|
|
|
-#define AQ_NIC_FC_OFF 0U
|
|
-#define AQ_NIC_FC_TX 1U
|
|
-#define AQ_NIC_FC_RX 2U
|
|
-#define AQ_NIC_FC_FULL 3U
|
|
-#define AQ_NIC_FC_AUTO 4U
|
|
-
|
|
#define AQ_CFG_FC_MODE AQ_NIC_FC_FULL
|
|
|
|
/* Default WOL modes used on initialization */
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
|
|
index 8286c77d43a5..6353a5c5ed27 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
|
|
@@ -588,7 +588,7 @@ static void aq_ethtool_get_pauseparam(struct net_device *ndev,
|
|
struct ethtool_pauseparam *pause)
|
|
{
|
|
struct aq_nic_s *aq_nic = netdev_priv(ndev);
|
|
- u32 fc = aq_nic->aq_nic_cfg.flow_control;
|
|
+ u32 fc = aq_nic->aq_nic_cfg.fc.req;
|
|
|
|
pause->autoneg = 0;
|
|
|
|
@@ -610,14 +610,14 @@ static int aq_ethtool_set_pauseparam(struct net_device *ndev,
|
|
return -EOPNOTSUPP;
|
|
|
|
if (pause->rx_pause)
|
|
- aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_RX;
|
|
+ aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_RX;
|
|
else
|
|
- aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_RX;
|
|
+ aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_RX;
|
|
|
|
if (pause->tx_pause)
|
|
- aq_nic->aq_hw->aq_nic_cfg->flow_control |= AQ_NIC_FC_TX;
|
|
+ aq_nic->aq_hw->aq_nic_cfg->fc.req |= AQ_NIC_FC_TX;
|
|
else
|
|
- aq_nic->aq_hw->aq_nic_cfg->flow_control &= ~AQ_NIC_FC_TX;
|
|
+ aq_nic->aq_hw->aq_nic_cfg->fc.req &= ~AQ_NIC_FC_TX;
|
|
|
|
mutex_lock(&aq_nic->fwreq_mutex);
|
|
err = aq_nic->aq_fw_ops->set_flow_control(aq_nic->aq_hw);
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index d3739f21b18e..7ad8eb535d28 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -79,7 +79,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
|
|
cfg->is_rss = AQ_CFG_IS_RSS_DEF;
|
|
cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF;
|
|
cfg->aq_rss.base_cpu_number = AQ_CFG_RSS_BASE_CPU_NUM_DEF;
|
|
- cfg->flow_control = AQ_CFG_FC_MODE;
|
|
+ cfg->fc.req = AQ_CFG_FC_MODE;
|
|
cfg->wol = AQ_CFG_WOL_MODES;
|
|
|
|
cfg->mtu = AQ_CFG_MTU_DEF;
|
|
@@ -144,6 +144,10 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
|
|
if (err)
|
|
return err;
|
|
|
|
+ if (self->aq_fw_ops->get_flow_control)
|
|
+ self->aq_fw_ops->get_flow_control(self->aq_hw, &fc);
|
|
+ self->aq_nic_cfg.fc.cur = fc;
|
|
+
|
|
if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) {
|
|
netdev_info(self->ndev, "%s: link change old %d new %d\n",
|
|
AQ_CFG_DRV_NAME, self->link_status.mbps,
|
|
@@ -161,8 +165,6 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)
|
|
* on any link event.
|
|
* We should query FW whether it negotiated FC.
|
|
*/
|
|
- if (self->aq_fw_ops->get_flow_control)
|
|
- self->aq_fw_ops->get_flow_control(self->aq_hw, &fc);
|
|
if (self->aq_hw_ops->hw_set_fc)
|
|
self->aq_hw_ops->hw_set_fc(self->aq_hw, fc, 0);
|
|
}
|
|
@@ -862,9 +864,12 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
100baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.aq_hw_caps->flow_control)
|
|
+ if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
Pause);
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
+ Asym_Pause);
|
|
+ }
|
|
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
|
|
|
|
@@ -898,13 +903,13 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
100baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX)
|
|
+ if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
Pause);
|
|
|
|
/* Asym is when either RX or TX, but not both */
|
|
- if (!!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX) ^
|
|
- !!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX))
|
|
+ if (!!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_TX) ^
|
|
+ !!(self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX))
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
Asym_Pause);
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
index 98c3182bf1d0..a752f8bb4b08 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h
|
|
@@ -20,6 +20,18 @@ struct aq_vec_s;
|
|
struct aq_ptp_s;
|
|
enum aq_rx_filter_type;
|
|
|
|
+enum aq_fc_mode {
|
|
+ AQ_NIC_FC_OFF = 0,
|
|
+ AQ_NIC_FC_TX,
|
|
+ AQ_NIC_FC_RX,
|
|
+ AQ_NIC_FC_FULL,
|
|
+};
|
|
+
|
|
+struct aq_fc_info {
|
|
+ enum aq_fc_mode req;
|
|
+ enum aq_fc_mode cur;
|
|
+};
|
|
+
|
|
struct aq_nic_cfg_s {
|
|
const struct aq_hw_caps_s *aq_hw_caps;
|
|
u64 features;
|
|
@@ -34,7 +46,7 @@ struct aq_nic_cfg_s {
|
|
u32 rxpageorder;
|
|
u32 num_rss_queues;
|
|
u32 mtu;
|
|
- u32 flow_control;
|
|
+ struct aq_fc_info fc;
|
|
u32 link_speed_msk;
|
|
u32 wol;
|
|
u8 is_vlan_rx_strip;
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
|
|
index d2fb399f179f..03b62d7d9f1a 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
|
|
@@ -155,7 +155,7 @@ static int hw_atl_a0_hw_qos_set(struct aq_hw_s *self)
|
|
|
|
/* QoS Rx buf size per TC */
|
|
tc = 0;
|
|
- is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control);
|
|
+ is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->fc.req);
|
|
buff_size = HW_ATL_A0_RXBUF_MAX;
|
|
|
|
hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc);
|
|
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 8686462b32f9..c5da60c12262 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
|
|
@@ -168,7 +168,7 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)
|
|
(1024U / 32U) * 50U) /
|
|
100U, tc);
|
|
|
|
- hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc);
|
|
+ hw_atl_b0_set_fc(self, self->aq_nic_cfg->fc.req, tc);
|
|
|
|
/* Init TC2 for PTP_RX */
|
|
tc = 2;
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
index ce3ed86d8c0e..97ebf849695f 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c
|
|
@@ -181,17 +181,26 @@ static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed)
|
|
return 0;
|
|
}
|
|
|
|
-static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state)
|
|
+static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self,
|
|
+ u32 *mpi_state, u32 fc)
|
|
{
|
|
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX)
|
|
- *mpi_state |= BIT(CAPS_HI_PAUSE);
|
|
- else
|
|
- *mpi_state &= ~BIT(CAPS_HI_PAUSE);
|
|
+ *mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE |
|
|
+ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE);
|
|
|
|
- if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX)
|
|
- *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE);
|
|
- else
|
|
- *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE);
|
|
+ switch (fc) {
|
|
+ /* There is not explicit mode of RX only pause frames,
|
|
+ * thus, we join this mode with FC full.
|
|
+ * FC full is either Rx, either Tx, or both.
|
|
+ */
|
|
+ case AQ_NIC_FC_FULL:
|
|
+ case AQ_NIC_FC_RX:
|
|
+ *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE |
|
|
+ HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
|
|
+ break;
|
|
+ case AQ_NIC_FC_TX:
|
|
+ *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE;
|
|
+ break;
|
|
+ }
|
|
}
|
|
|
|
static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts,
|
|
@@ -215,7 +224,8 @@ static int aq_fw2x_set_state(struct aq_hw_s *self,
|
|
case MPI_INIT:
|
|
mpi_state &= ~BIT(CAPS_HI_LINK_DROP);
|
|
aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds);
|
|
- aq_fw2x_set_mpi_flow_control(self, &mpi_state);
|
|
+ aq_fw2x_upd_flow_control_bits(self, &mpi_state,
|
|
+ self->aq_nic_cfg->fc.req);
|
|
break;
|
|
case MPI_DEINIT:
|
|
mpi_state |= BIT(CAPS_HI_LINK_DROP);
|
|
@@ -525,7 +535,8 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
|
|
{
|
|
u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR);
|
|
|
|
- aq_fw2x_set_mpi_flow_control(self, &mpi_state);
|
|
+ aq_fw2x_upd_flow_control_bits(self, &mpi_state,
|
|
+ self->aq_nic_cfg->fc.req);
|
|
|
|
aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state);
|
|
|
|
@@ -535,17 +546,13 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self)
|
|
static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode)
|
|
{
|
|
u32 mpi_state = aq_fw2x_state2_get(self);
|
|
+ *fcmode = 0;
|
|
|
|
if (mpi_state & HW_ATL_FW2X_CAP_PAUSE)
|
|
- if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
|
|
- *fcmode = AQ_NIC_FC_RX;
|
|
- else
|
|
- *fcmode = AQ_NIC_FC_RX | AQ_NIC_FC_TX;
|
|
- else
|
|
- if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
|
|
- *fcmode = AQ_NIC_FC_TX;
|
|
- else
|
|
- *fcmode = 0;
|
|
+ *fcmode |= AQ_NIC_FC_RX;
|
|
+
|
|
+ if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE)
|
|
+ *fcmode |= AQ_NIC_FC_TX;
|
|
|
|
return 0;
|
|
}
|
|
--
|
|
2.13.6
|
|
|