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.
292 lines
11 KiB
292 lines
11 KiB
From 0a2ffafa7bd0fdac22c58063462fad89fadf63ad Mon Sep 17 00:00:00 2001
|
|
From: Igor Russkikh <irusskik@redhat.com>
|
|
Date: Fri, 6 Nov 2020 18:38:02 -0500
|
|
Subject: [PATCH 105/139] [netdrv] net: atlantic: A2: half duplex support
|
|
|
|
Message-id: <1604687916-15087-106-git-send-email-irusskik@redhat.com>
|
|
Patchwork-id: 338527
|
|
Patchwork-instance: patchwork
|
|
O-Subject: [RHEL8.4 BZ 1857861 105/139] net: atlantic: A2: half duplex support
|
|
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 071a02046c262f633ef8d9064cf36fd6def6d0a5
|
|
Author: Igor Russkikh <irusskikh@marvell.com>
|
|
Date: Mon Jun 22 17:53:04 2020 +0300
|
|
|
|
net: atlantic: A2: half duplex support
|
|
|
|
This patch adds support for 10M/100M/1G half duplex rates, which are
|
|
supported by A2 in additional to full duplex rates supported by A1.
|
|
|
|
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_common.h | 13 +++--
|
|
drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 8 +--
|
|
drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 60 +++++++++++++++++-----
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils.c | 1 +
|
|
.../aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c | 1 +
|
|
.../ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c | 5 +-
|
|
.../aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c | 5 ++
|
|
7 files changed, 70 insertions(+), 23 deletions(-)
|
|
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
|
|
index 52ad9433cabc..1587528ca3f6 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h
|
|
@@ -58,11 +58,14 @@
|
|
#define AQ_NIC_RATE_1G BIT(4)
|
|
#define AQ_NIC_RATE_100M BIT(5)
|
|
#define AQ_NIC_RATE_10M BIT(6)
|
|
+#define AQ_NIC_RATE_1G_HALF BIT(7)
|
|
+#define AQ_NIC_RATE_100M_HALF BIT(8)
|
|
+#define AQ_NIC_RATE_10M_HALF BIT(9)
|
|
|
|
-#define AQ_NIC_RATE_EEE_10G BIT(7)
|
|
-#define AQ_NIC_RATE_EEE_5G BIT(8)
|
|
-#define AQ_NIC_RATE_EEE_2G5 BIT(9)
|
|
-#define AQ_NIC_RATE_EEE_1G BIT(10)
|
|
-#define AQ_NIC_RATE_EEE_100M BIT(11)
|
|
+#define AQ_NIC_RATE_EEE_10G BIT(10)
|
|
+#define AQ_NIC_RATE_EEE_5G BIT(11)
|
|
+#define AQ_NIC_RATE_EEE_2G5 BIT(12)
|
|
+#define AQ_NIC_RATE_EEE_1G BIT(13)
|
|
+#define AQ_NIC_RATE_EEE_100M BIT(14)
|
|
|
|
#endif /* AQ_COMMON_H */
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
index 4a7fea467b78..a8efd6543f97 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h
|
|
@@ -1,7 +1,8 @@
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
-/*
|
|
- * aQuantia Corporation Network Driver
|
|
- * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved
|
|
+/* Atlantic Network Driver
|
|
+ *
|
|
+ * Copyright (C) 2014-2019 aQuantia Corporation
|
|
+ * Copyright (C) 2019-2020 Marvell International Ltd.
|
|
*/
|
|
|
|
/* File aq_hw.h: Declaration of abstract interface for NIC hardware specific
|
|
@@ -69,6 +70,7 @@ struct aq_hw_caps_s {
|
|
|
|
struct aq_hw_link_status_s {
|
|
unsigned int mbps;
|
|
+ bool full_duplex;
|
|
};
|
|
|
|
struct aq_stats_s {
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
index 04d2faae298b..45d33797fa73 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c
|
|
@@ -923,8 +923,11 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
cmd->base.port = PORT_FIBRE;
|
|
else
|
|
cmd->base.port = PORT_TP;
|
|
- /* This driver supports only 10G capable adapters, so DUPLEX_FULL */
|
|
- cmd->base.duplex = DUPLEX_FULL;
|
|
+
|
|
+ cmd->base.duplex = DUPLEX_UNKNOWN;
|
|
+ if (self->link_status.mbps)
|
|
+ cmd->base.duplex = self->link_status.full_duplex ?
|
|
+ DUPLEX_FULL : DUPLEX_HALF;
|
|
cmd->base.autoneg = self->aq_nic_cfg.is_autoneg;
|
|
|
|
ethtool_link_ksettings_zero_link_mode(cmd, supported);
|
|
@@ -945,14 +948,26 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
1000baseT_Full);
|
|
|
|
+ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
+ 1000baseT_Half);
|
|
+
|
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M)
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
100baseT_Full);
|
|
|
|
+ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
+ 100baseT_Half);
|
|
+
|
|
if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M)
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
10baseT_Full);
|
|
|
|
+ if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10M_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
+ 10baseT_Half);
|
|
+
|
|
if (self->aq_nic_cfg.aq_hw_caps->flow_control) {
|
|
ethtool_link_ksettings_add_link_mode(cmd, supported,
|
|
Pause);
|
|
@@ -972,30 +987,42 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
if (self->aq_nic_cfg.is_autoneg)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10G)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
10000baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_5G)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
5000baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_2G5)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
2500baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
1000baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_1G_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
+ 1000baseT_Half);
|
|
+
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
100baseT_Full);
|
|
|
|
- if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_100M_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
+ 100baseT_Half);
|
|
+
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
10baseT_Full);
|
|
|
|
+ if (self->aq_nic_cfg.link_speed_msk & AQ_NIC_RATE_10M_HALF)
|
|
+ ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
+ 10baseT_Half);
|
|
+
|
|
if (self->aq_nic_cfg.fc.cur & AQ_NIC_FC_RX)
|
|
ethtool_link_ksettings_add_link_mode(cmd, advertising,
|
|
Pause);
|
|
@@ -1015,27 +1042,32 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,
|
|
int aq_nic_set_link_ksettings(struct aq_nic_s *self,
|
|
const struct ethtool_link_ksettings *cmd)
|
|
{
|
|
- u32 speed = 0U;
|
|
+ int fduplex = (cmd->base.duplex == DUPLEX_FULL);
|
|
+ u32 speed = cmd->base.speed;
|
|
u32 rate = 0U;
|
|
int err = 0;
|
|
|
|
+ if (!fduplex && speed > SPEED_1000) {
|
|
+ err = -EINVAL;
|
|
+ goto err_exit;
|
|
+ }
|
|
+
|
|
if (cmd->base.autoneg == AUTONEG_ENABLE) {
|
|
rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk;
|
|
self->aq_nic_cfg.is_autoneg = true;
|
|
} else {
|
|
- speed = cmd->base.speed;
|
|
-
|
|
switch (speed) {
|
|
case SPEED_10:
|
|
- rate = AQ_NIC_RATE_10M;
|
|
+ rate = fduplex ? AQ_NIC_RATE_10M : AQ_NIC_RATE_10M_HALF;
|
|
break;
|
|
|
|
case SPEED_100:
|
|
- rate = AQ_NIC_RATE_100M;
|
|
+ rate = fduplex ? AQ_NIC_RATE_100M
|
|
+ : AQ_NIC_RATE_100M_HALF;
|
|
break;
|
|
|
|
case SPEED_1000:
|
|
- rate = AQ_NIC_RATE_1G;
|
|
+ rate = fduplex ? AQ_NIC_RATE_1G : AQ_NIC_RATE_1G_HALF;
|
|
break;
|
|
|
|
case SPEED_2500:
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
index 73c0f41df8d8..1d9dee4951f9 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
|
|
@@ -704,6 +704,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
+ link_status->full_duplex = true;
|
|
|
|
return 0;
|
|
}
|
|
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 8296a1e63522..92ae60ac5735 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
|
|
@@ -271,6 +271,7 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self)
|
|
} else {
|
|
link_status->mbps = 0;
|
|
}
|
|
+ link_status->full_duplex = true;
|
|
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
|
|
index 8df9d4ef36f0..239d077e21d7 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2.c
|
|
@@ -64,8 +64,11 @@ const struct aq_hw_caps_s hw_atl2_caps_aqc113 = {
|
|
AQ_NIC_RATE_5G |
|
|
AQ_NIC_RATE_2G5 |
|
|
AQ_NIC_RATE_1G |
|
|
+ AQ_NIC_RATE_1G_HALF |
|
|
AQ_NIC_RATE_100M |
|
|
- AQ_NIC_RATE_10M,
|
|
+ AQ_NIC_RATE_100M_HALF |
|
|
+ AQ_NIC_RATE_10M |
|
|
+ AQ_NIC_RATE_10M_HALF,
|
|
};
|
|
|
|
static u32 hw_atl2_sem_act_rslvr_get(struct aq_hw_s *self)
|
|
diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c
|
|
index 0ffc33bd67d0..d64dfae8803e 100644
|
|
--- a/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c
|
|
+++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl2/hw_atl2_utils_fw.c
|
|
@@ -135,6 +135,10 @@ static void a2_link_speed_mask2fw(u32 speed,
|
|
link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G);
|
|
link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M);
|
|
link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M);
|
|
+
|
|
+ link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF);
|
|
+ link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF);
|
|
+ link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF);
|
|
}
|
|
|
|
static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed)
|
|
@@ -202,6 +206,7 @@ static int aq_a2_fw_update_link_status(struct aq_hw_s *self)
|
|
default:
|
|
self->aq_link_status.mbps = 0;
|
|
}
|
|
+ self->aq_link_status.full_duplex = link_status.duplex;
|
|
|
|
return 0;
|
|
}
|
|
--
|
|
2.13.6
|
|
|