When selecting a fixed speed of the link, whether or not
autonegotiation (e.g. AN Clause 37, etc.), needs to be enabled depends
on the peer link. While commit 3dc2933866d9 ("net/ice: disable link
negotiation for fixed speed selection") would allow link setup when the
remote side also has a fixed link without AN37 auto-negotiation, it
causes the link to flap up and down when e.g. two ports are connected
back to back and only one is set to a fixed speed.

Support both scenarios of auto-negotiation supported or unsupported on
the remote end by adding an explicit driver option for disabling
auto-negotiation when a fixed speed is selected. If no fixed speed
setting, then new option does nothing.

Fixes: 3dc2933866d9 ("net/ice: disable link negotiation for fixed speed 
selection")

Signed-off-by: Bruce Richardson <[email protected]>
---
 doc/guides/nics/ice.rst                | 10 ++++++++++
 doc/guides/rel_notes/release_26_11.rst |  2 ++
 drivers/net/intel/ice/ice_ethdev.c     | 23 +++++++++++++++++++----
 drivers/net/intel/ice/ice_ethdev.h     |  1 +
 4 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/doc/guides/nics/ice.rst b/doc/guides/nics/ice.rst
index faebfdcb63..15388f0185 100644
--- a/doc/guides/nics/ice.rst
+++ b/doc/guides/nics/ice.rst
@@ -107,6 +107,16 @@ Configuration
 Runtime Configuration
 ~~~~~~~~~~~~~~~~~~~~~
 
+``auto_neg_disable`` (default ``0``)
+   Control hardware link negotiation when a fixed speed is requested with 
``RTE_ETH_LINK_SPEED_FIXED``.
+   By default, the firmware's negotiation settings are preserved,
+   allowing a fixed-speed link to use negotiation such as Clause 37 when 
required by its peer.
+   Set ``auto_neg_disable=1`` to disable Clause 28, Clause 37 and Clause 73 
negotiation.
+   This option has no effect when automatic speed selection is requested.
+   For example::
+
+      -a 80:00.0,auto_neg_disable=1
+
 - ``Safe Mode Support`` (default ``0``)
 
   If driver failed to load OS package, by default driver's initialization 
failed.
diff --git a/doc/guides/rel_notes/release_26_11.rst 
b/doc/guides/rel_notes/release_26_11.rst
index 9e120ec221..96bd0ed7ca 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -175,6 +175,8 @@ New Features
 
 * **Updated Intel ice driver.**
 
+  * Added ``auto_neg_disable`` devarg to disable hardware link negotiation for 
fixed-speed links.
+    By default, fixed-speed links now preserve the firmware's negotiation 
settings.
   * Added chip temperature to the extended statistics.
   * Added Tx context descriptor support to the AVX2 and AVX512 vector Tx paths,
     enabling QinQ tag insertion and outer IPv4/UDP checksum offloads on those 
paths.
diff --git a/drivers/net/intel/ice/ice_ethdev.c 
b/drivers/net/intel/ice/ice_ethdev.c
index d2ba64efb6..b18b4bbb05 100644
--- a/drivers/net/intel/ice/ice_ethdev.c
+++ b/drivers/net/intel/ice/ice_ethdev.c
@@ -45,6 +45,7 @@
 #define ICE_RL_BURST_SIZE_ARG     "rl_burst_size"
 #define ICE_SOURCE_PRUNE_ARG      "source-prune"
 #define ICE_LINK_STATE_ON_CLOSE   "link_state_on_close"
+#define ICE_AUTO_NEG_DISABLE_ARG  "auto_neg_disable"
 
 #define ICE_CYCLECOUNTER_MASK  0xffffffffffffffffULL
 
@@ -64,6 +65,7 @@ static const char * const ice_valid_args[] = {
        ICE_RL_BURST_SIZE_ARG,
        ICE_SOURCE_PRUNE_ARG,
        ICE_LINK_STATE_ON_CLOSE,
+       ICE_AUTO_NEG_DISABLE_ARG,
        NULL
 };
 
@@ -2542,6 +2544,11 @@ static int ice_parse_devargs(struct rte_eth_dev *dev)
 
        ret = rte_kvargs_process(kvlist, ICE_LINK_STATE_ON_CLOSE,
                                 &parse_link_state_on_close, 
&ad->devargs.link_state_on_close);
+       if (ret)
+               goto bail;
+
+       ret = rte_kvargs_process(kvlist, ICE_AUTO_NEG_DISABLE_ARG,
+                                &parse_bool, &ad->devargs.auto_neg_disable);
 
 bail:
        rte_kvargs_free(kvlist);
@@ -5092,6 +5099,15 @@ ice_atomic_write_link_status(struct rte_eth_dev *dev,
        return 0;
 }
 
+static bool
+ice_link_autoneg_enabled(const struct rte_eth_dev *dev)
+{
+       const struct ice_adapter *ad = 
ICE_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
+
+       return !ad->devargs.auto_neg_disable ||
+                       (dev->data->dev_conf.link_speeds & 
RTE_ETH_LINK_SPEED_FIXED) == 0;
+}
+
 static int
 ice_link_update(struct rte_eth_dev *dev, int wait_to_complete)
 {
@@ -5180,8 +5196,7 @@ ice_link_update(struct rte_eth_dev *dev, int 
wait_to_complete)
                break;
        }
 
-       link.link_autoneg = !(dev->data->dev_conf.link_speeds &
-                             RTE_ETH_LINK_SPEED_FIXED);
+       link.link_autoneg = ice_link_autoneg_enabled(dev);
 
 out:
        ice_atomic_write_link_status(dev, &link);
@@ -5248,8 +5263,7 @@ ice_apply_link_speed(struct rte_eth_dev *dev)
                return -EINVAL;
        }
 
-       bool link_autoneg = (conf->link_speeds & RTE_ETH_LINK_SPEED_FIXED) == 0;
-       return ice_phy_conf_link(hw, speed, true, link_autoneg);
+       return ice_phy_conf_link(hw, speed, true, 
ice_link_autoneg_enabled(dev));
 }
 
 static int
@@ -8198,6 +8212,7 @@ RTE_PMD_REGISTER_PARAM_STRING(net_ice,
                              ICE_RL_BURST_SIZE_ARG "=<N>"
                              ICE_SOURCE_PRUNE_ARG "=<0|1>"
                              ICE_RX_LOW_LATENCY_ARG "=<0|1>"
+                             ICE_AUTO_NEG_DISABLE_ARG "=<0|1>"
                              ICE_LINK_STATE_ON_CLOSE "=<down|up|initial>");
 
 RTE_LOG_REGISTER_SUFFIX(ice_logtype_init, init, NOTICE);
diff --git a/drivers/net/intel/ice/ice_ethdev.h 
b/drivers/net/intel/ice/ice_ethdev.h
index 945e765c2c..747c003bb3 100644
--- a/drivers/net/intel/ice/ice_ethdev.h
+++ b/drivers/net/intel/ice/ice_ethdev.h
@@ -634,6 +634,7 @@ struct ice_pf {
 struct ice_devargs {
        bool rx_low_latency;
        bool safe_mode_support;
+       bool auto_neg_disable;
        uint8_t proto_xtr_dflt;
        bool default_mac_disable;
        uint8_t proto_xtr[ICE_MAX_QUEUE_NUM];
-- 
2.55.0

Reply via email to